Skill v1.0.1
currentAutomated scan100/100+2 new
version: "1.0.1" name: teradata-mcp-customisation description: Use when the task is to build, edit, or debug a semantic layer for the Teradata MCP server (https://github.com/Teradata/teradata-mcp-server) — custom tools, cubes, prompts, and glossary entries declared in YAML, plus the profiles.yml that exposes them. Covers schema rules, the cube SQL wrapping model, parameter substitution, profile regex selection, and the runtime smoke-test flow.
You are extending the Teradata MCP server with a semantic layer: domain-specific tools, cubes, prompts, and glossary terms declared in YAML files that the server picks up at startup.
The server is the upstream project at https://github.com/Teradata/teradata-mcp-server. The customisation surface is documented in docs/server_guide/CUSTOMIZING.md; this skill compiles the parts that are easy to get wrong, plus working examples that anyone can run against the DBC system database.
When to use this skill
- Designing a new semantic layer for a Teradata data product (cubes + curated prompts).
- Adding or editing a custom tool / cube / prompt / glossary entry.
- Building a
profiles.ymlto expose a subset of objects to a given client. - Debugging why a custom object does not appear in
tools/list,prompts/list, orresources/list. - Migrating a hand-written SQL pattern into a reusable cube the LLM can compose.
Mental model — what each object becomes at runtime
YAML type: | Where it surfaces | Selected by profile section | |
|---|---|---|---|
tool | MCP tool — parameterised SQL the LLM calls | tool: | |
cube | MCP tool — the server auto-generates a 6-arg aggregator (dimensions, measures, filter, res_filter, order_by, top) plus any custom params you declare | tool: | |
prompt | MCP prompt — a reusable system / user prompt the client can fetch by name | prompt: | |
glossary | MCP resource — domain terms surfaced as context resources, enriched with cube measure/dim descriptions | resource: |
There is no type: resource. Resources are derived: glossary entries become resources, and cube/tool descriptions feed back into glossary enrichment.
Workflow
- Locate the config directory. The server reads YAML from
--config_dir(CLI) or$CONFIG_DIR(env), defaulting to the current working directory. Drop one or more*.ymlfiles there alongsideprofiles.yml. Multiple files merge into one namespace keyed by object name. - Pick the object type for what you are building. If in doubt, see
reference/object-types.md. - Write the SQL first, in isolation. Run it in your usual Teradata client until it returns what you want — then wrap it as a tool or cube. For cubes, write the flat denormalised base SQL; let the server build the aggregator on top. See
reference/cube-mechanics.mdfor exactly how the wrapping works (which is critical for understanding filter vs res_filter semantics). - Get parameter substitution right. Custom tools support two styles:
:paramfor value binds,{param}for identifier interpolation (database / table names). Cubes also accept custom parameters used inside the base SQL the same way. Seereference/parameter-substitution.md. - Expose via `profiles.yml`. Add a profile (or extend an existing one) with regex selectors. See
reference/profiles.mdfor the layering rules and the built-in profiles you can inherit from. - Smoke-test the server with the MCP listing flow before pointing a client at it. See
reference/deployment.mdfor the bash curl recipe (initialize→notifications/initialized→tools/list).
Authoring rules (important — don't skip)
- Descriptions are the contract. The
descriptionfields on tools, cubes, dimensions, measures, and parameters are what the LLM reads to choose and shape its calls. Write them like terse API docs: what it represents, units, when to use it, when not to. The server appends type info automatically — don't repeat it. - Cubes are filtered twice.
filterapplies before aggregation and can use cube dimension names even when those dimensions are not selected.res_filterapplies afterGROUP BY(use result measure names —nii > 1000notSUM(nii_v) > 1000). Get this wrong and the LLM will write filters that error or return nothing. - Pin the domain in the base SQL `WHERE`. Hard-code the filters that define what the cube is (one product family, one subject area). Do not leave that decision to
filter— the LLM will forget or invent. - Keep the menu small. Aim for ~10 dimensions and ~15 measures per cube. More than that and selection accuracy drops sharply. Split into two cubes if you have a wider surface.
- Aggregate measure expressions are first-class. A measure
expression:is whatever Teradata SQL evaluates to a scalar over the group —SUM(...), ratios withNULLIFZERO, evenSUM(x) OVER ()for "share of total" measures. The server inlines it asexpression AS measure_name. - Never embed credentials in cube/tool SQL or in
profiles.yml. Connection strings belong inprofiles.yml'srun:block via env-var substitution (${TD_USER},${TD_PASSWORD}), or in the server's own startup env. - Name with a domain prefix.
sales_growth_cube,dba_space_cube. A single regex (sales_.*) then selects the whole pack into a profile. - Prompts are not auto-attached. A
type: promptis a callable resource the client fetches by name — it is not silently injected into every conversation. Document that in your prompt'sdescription.
Progressive references
Load these only when needed:
reference/object-types.md— full YAML schemas fortool,cube,prompt,glossarywith every field and what each does.reference/cube-mechanics.md— the exact SELECT the server generates around your base SQL, plus the auto-added cube parameters (dimensions,measures,filter,res_filter,order_by,top).reference/parameter-substitution.md—:namevalue binds vs{name}identifier formatting, the synthetic{table_ref}key, supportedtype_hintvalues, and the auto-addedpersistparameter on custom tools.reference/profiles.md— howprofiles.ymllayers over the packaged profiles, regex selector rules, therun:block (transport / port / database URI), and the built-in profiles you can extend (all,eda,dba,dataScientist, …).reference/deployment.md—config_dirresolution, server launch, and the bare-bones curl smoke-test that walks the streamable-HTTP MCP handshake to list tools / prompts / resources.
Worked examples (DBC-only, portable)
All examples target DBC system views so anyone with Teradata access can run them without setting up sample data:
examples/example_tool.yml— a parameterised tool that lists the N largest tables in a given database (DBC.AllSpaceV).examples/example_cube.yml— a "database space" cube onDBC.AllSpaceVwith dimensions (database, account, owner) and measures (current_perm, peak_perm, skew_factor).examples/example_prompt.yml— a Teradata DBA persona prompt with a{focus_area}parameter.examples/example_glossary.yml— glossary entries forpermspace,spool,skew factor.examples/example_profiles.yml— adbc_demoprofile that selects the four objects above by regex, plus inherited read-only base tools.
Copy any of these into a *.yml file in your config dir, restart the server, and they will appear in the relevant MCP list.