Create or update a Coral source spec YAML for a custom HTTP API or local dataset. Use when authoring a standalone source for `coral source add --file`, or when adapting that spec into a Coral repo source under `sources/core` or `sources/community`.
72
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Use this skill when the task is to author or repair a Coral source spec.
Produce a valid, queryable Coral source spec that works with:
coral source lint <path>coral source add --file <path>coral source test <name>coral sqlcoral.tables and coral.columnscoral.inputs for source variables and secretsDefault to standalone source authoring for external developers.
That means:
coral source lint <path>coral source add --file <path> when you need to exercise it as a sourceOnly switch to Coral repo layout when the user is explicitly editing the Coral repo.
./my-source.yamlcoral source lint ./my-source.yamlcoral source add --file ./my-source.yaml when you need to query it through Coralsources/community/<name>/manifest.yamlsources/core/<name>/manifest.yaml only when the user is intentionally changing bundled core sourcestest_queries for a basic smoke/connection check of the sourcecoral source test <name> and repo checkskind: identity manifest, identity setup inputs and OAuth method configcoral source lint <path>coral source add --file <path> and inspect with coral sqlcoral source add is non-interactive by default: each input key is read from the matching environment variable. Export required variables and secrets before running, or pass --interactive to be prompted.coral source add --interactive --file <path> with no environment value for the target secret so Coral offers the authored credential choicescoral source test <name>coral.tables for visible tables, descriptions, guides, and required filters; keep metadata queries bounded with LIMIT/OFFSETcoral.table_functions for source-scoped functions, descriptions, guides, arguments, result columns, kind, and search limitscoral.columns for canonical column metadata, including is_virtual and is_required_filter; filter by one table or page large column setscoral.filters for normalized table filter names, types, modes, required flags, and descriptionscoral.inputs to verify variables, secrets, defaults, hints, and required flagscoral sql.coral source test, make sure test_queries gives you a basic smoke/connection check for the source.inputs.<TOKEN>.credential.methods[] using type: oauth; keep the runtime auth or request header pointing at the same secret input.flow.type: authorization_code, set flow.pkce explicitly to required or disabled, use a loopback http://127.0.0.1 or http://localhost redirect URI, choose redirect_uri_port_mode: random for provider apps or Dynamic Client Registration endpoints that allow variable localhost ports, and choose fixed only when users can register the exact non-zero redirect URI. The CLI also accepts the final loopback redirect URL pasted into the terminal when the browser cannot reach the machine running Coral, so do not reject authorization-code OAuth solely because users may run Coral over SSH, in a VM, or in another split-browser environment. For device-code flow, declare flow.type: device_code, endpoints.device_authorization_url, endpoints.token_url, and either a public client ID or client.dynamic_registration; omit redirect URI fields and do not declare a static client secret.client.dynamic_registration.registration_url over hard-coding a shared public client ID. Coral always registers a native client; source specs cannot configure a web Dynamic Client Registration application type. Set token_endpoint_auth_method to none, client_secret_basic, or client_secret_post to match the registered client type. Set request_refresh_token_grant: true only when the provider supports registering clients for refresh-token grants. For OAuth-protected Streamable HTTP MCP servers, set oauth.resource to the MCP server URL when the provider requires resource indicators.kind: variable inputs with {{input.KEY}} for non-secret endpoint components such as tenant IDs or domains. This includes endpoints.*, resource, and client.dynamic_registration.registration_url. Do not reference secret inputs, filters, function arguments, state, or inline defaults from OAuth URLs.type: source_config fallback after the OAuth method. When the provider's token endpoint requires client authentication with a client secret, prompt for both OAuth client values: declare client.id.input, client.secret.input, and client.secret.transport (basic_auth or request_body).client.id.input and client.secret.input are collected during OAuth setup.kind: identity manifest, put provider issuer, identity type, setup inputs, OAuth URLs, client IDs, and client secrets on the identity spec itself. Identity OAuth client.id may use default, a variable input, or both; client.secret.input must reference a declared secret input. OAuth URL templates may reference only declared variable inputs. Identity inputs must not declare source credential methods.label, description, and hint fields, surfaced during interactive install and in the generated source docs. When an input offers more than one method, put the how-to-get-it guidance in each method's hint (rendered next to that method's fields) instead of in one long input-level hint, and scope each hint to the inputs that method collects.snake_case
table names. Table-function names must start with an ASCII letter or
underscore and then use only ASCII letters, numbers, or underscores.kind: search table functions for provider endpoints that accept query text and return ranked candidates.type when the provider argument is not string-shaped; omitted arg types default to Utf8.mode: contains only for ordinary provider-side substring filters. Provider-ranked retrieval belongs in a kind: search function.search_limits on every kind: search function and expose stable result identifiers for follow-up detail queries.COUNT(*).test_queries when you want coral source test to perform a basic smoke/connection check.Use these rules for top-level source metadata so source discovery and setup are consistent.
descriptionQuery ....Query <entities> from <Provider> (<Cloud or self-hosted when relevant>).description focused on data coverage, not setup steps.REST API v3OpenAPI provider... and moreinputs.<KEY>.hint)Each hint should tell the user:
Specific guidance:
label such as Connect with GitHubdescription to a short one-line blurb; put the setup detail in the method's hinthint, list the required OAuth scopes and explain whether users must register a fixed loopback redirect URI or provide their own OAuth client ID/secret; when the method collects client.id.input/client.secret.input, say where to obtain those valueshint that users can paste the final localhost redirect URL into the terminal if their browser cannot reach Coral's loopback listener directlyhint to the inputs that method collects instead of writing one broad input-level hint that mixes guidance for every methodKeep hints concise and directly actionable.
Use this loop during authoring:
# Export any required inputs first (key matches the input `key` in the spec),
# or pass --interactive to be prompted.
coral source lint ./my-source.yaml
coral source add --file ./my-source.yaml
coral source test my_source
coral sql "SELECT catalog_name, schema_name, table_name, description, required_filters FROM coral.tables WHERE schema_name = 'my_source' OR catalog_name = 'my_source' ORDER BY catalog_name, schema_name, table_name LIMIT 50 OFFSET 0"
coral sql "SELECT function_name, kind, arguments_json, result_columns_json, search_limits_json FROM coral.table_functions WHERE schema_name = 'my_source' ORDER BY function_name LIMIT 50 OFFSET 0"
coral sql "SELECT table_name, filter_name, filter_mode, is_required, data_type, description FROM coral.filters WHERE schema_name = 'my_source' OR catalog_name = 'my_source' ORDER BY table_name, filter_name LIMIT 100 OFFSET 0"
coral sql "SELECT table_name, column_name, data_type, is_virtual, is_required_filter, filter_mode, description FROM coral.columns WHERE schema_name = 'my_source' OR catalog_name = 'my_source' ORDER BY table_name, ordinal_position LIMIT 100 OFFSET 0"
coral sql "SELECT catalog_name, key, kind, value, default_value, hint, required, is_set FROM coral.inputs WHERE schema_name = 'my_source' OR catalog_name = 'my_source' ORDER BY key"Each WHERE clause matches on both qualifiers because a source is addressed
either by schema or by catalog. Schema-addressed sources carry the source name in
schema_name and leave catalog_name empty; database sources put the source name
in catalog_name, and their coral.inputs rows have an empty schema_name.
Filtering on schema_name alone returns zero rows for a database source without
reporting an error, which reads as "this source declares nothing".
For repo sources or already-named sources, add test_queries for a basic smoke/connection check and run:
coral source test my_sourceThen run targeted table queries until the source behaves correctly.
For HTTP-backed sources:
backend: httpbase_urlcredential.methods on secret inputs when setup should offer OAuth or another retrieval choicerows_pathtest_queries once you know which simple query or queries should confirm the source basically worksRead references/http-source-checklist.md when you need table-shape and pagination guidance.
If your HTTP source uses an Authorization header with a prefix (e.g. Authorization: Bearer <token>), use a secret input for the raw token and define the header with from: bearer:
inputs:
FOOBAR_API_TOKEN:
kind: secret
hint: Bearer token for the Foobar API.
auth:
type: HeaderAuth
headers:
- name: Authorization
from: bearer
key: FOOBAR_API_TOKENFor an OAuth-backed HTTP source, add the retrieval method to that same secret input:
inputs:
FOOBAR_API_TOKEN:
kind: secret
hint: Connect with Foobar OAuth or paste a token with read access.
credential:
methods:
- type: oauth
label: Connect with Foobar
description: Open a browser and authorize Coral to read Foobar data.
hint: |
Signs you in through Foobar and requests the `read` scope. To
use your own app, set FOOBAR_OAUTH_CLIENT_ID to its Client ID.
oauth:
flow:
type: authorization_code
pkce: required
redirect_uri: http://127.0.0.1:0/oauth/callback
redirect_uri_port_mode: random
endpoints:
authorization_url: https://foobar.example.com/oauth/authorize
token_url: https://foobar.example.com/oauth/token
client:
id:
input: FOOBAR_OAUTH_CLIENT_ID
scopes:
scope:
delimiter: space
values:
- read
- type: source_config
label: Paste token
hint: Paste a Foobar API token with read access to the data you query.
auth:
type: HeaderAuth
headers:
- name: Authorization
from: bearer
key: FOOBAR_API_TOKENWhen a provider accepts either a full pasted API-key header or an OAuth access token, declare both credential inputs as optional secrets, then use from: one_of and put the complete header value first, followed by a from: bearer OAuth fallback:
inputs:
FOOBAR_API_KEY:
kind: secret
required: false
FOOBAR_OAUTH_ACCESS_TOKEN:
kind: secret
required: false
auth:
type: HeaderAuth
headers:
- name: Authorization
from: one_of
values:
- from: input
key: FOOBAR_API_KEY
- from: bearer
key: FOOBAR_OAUTH_ACCESS_TOKENFor local file-backed sources:
Report:
334387d
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.