Loading...
Loading...
Build and maintain an executable context layer for data and analytics agents using ktx's semantic layer, wiki knowledge, and MCP integration
npx skill4agent add aradotso/mcp-skills ktx-ai-data-context-layerSkill by ara.so — MCP Skills collection.
npm install -g @kaelio/ktxnpm install @kaelio/ktxktx --versionktx setupktx statusktx project: /home/user/analytics
Project ready: yes
LLM ready: yes (claude-sonnet-4-6)
Embeddings ready: yes (text-embedding-3-small)
Databases configured: yes (warehouse)
Context sources configured: yes (dbt_main)
ktx context built: yes
Agent integration ready: yes (codex:project)my-project/
├── ktx.yaml # Project configuration
├── semantic-layer/<connection-id>/ # YAML semantic sources
├── wiki/global/ # Shared business context
├── wiki/user/<user-id>/ # User-scoped notes
├── raw-sources/<connection-id>/ # Ingest artifacts and reports
└── .ktx/ # Local state and secrets (git-ignored)ktx.yamlsemantic-layer/wiki/.ktx/version: 1
project_name: analytics
# LLM configuration
llm:
provider: anthropic
model: claude-sonnet-4-6
api_key_env: ANTHROPIC_API_KEY
# Embedding configuration
embeddings:
provider: openai
model: text-embedding-3-small
api_key_env: OPENAI_API_KEY
# Database connections
connections:
warehouse:
type: postgres
host: localhost
port: 5432
database: analytics
schema: public
user_env: POSTGRES_USER
password_env: POSTGRES_PASSWORD
# Context sources
context_sources:
- id: dbt_main
type: dbt
path: ./dbt_project
- id: notion_wiki
type: notion
api_key_env: NOTION_API_KEY
database_ids:
- abc123def456# Anthropic API
ktx config set llm.provider anthropic
ktx config set llm.api_key_env ANTHROPIC_API_KEY
# Google Vertex AI
ktx config set llm.provider vertex
ktx config set llm.project_id my-gcp-project
# AI Gateway
ktx config set llm.provider ai-gateway
ktx config set llm.gateway_url https://gateway.example.comktx connection add warehouse \
--type postgres \
--host localhost \
--port 5432 \
--database analytics \
--user-env POSTGRES_USER \
--password-env POSTGRES_PASSWORDktx connection test warehousektx ingestktx ingest --connection warehouse# Sample more tables (default 100)
ktx ingest --sample-size 500
# Skip expensive operations
ktx ingest --skip-column-profiling
# Force re-ingest even if unchanged
ktx ingest --forcektx sl "revenue"
ktx sl "monthly active users"ktx wiki "refund policy"
ktx wiki "how to calculate churn"ktx semantic listktx semantic show usersktx semantic edit usersktx wiki create --title "Metric Definitions" --content-file metrics.mdktx wiki listktx wiki edit "Metric Definitions"ktx mcp startktx mcp start --project-dir /path/to/analyticsnpx skills add Kaelio/ktx --skill ktxktx mcp start --project-dir /path/to/projectUse ktx to search for revenue metrics and show me the SQL definitionsearch_semantic_layersearch_wikiget_table_schemaget_metric_definitiondetect_joinsvalidate_queryimport { spawn } from 'child_process';
async function searchSemanticLayer(query: string): Promise<string> {
return new Promise((resolve, reject) => {
const ktx = spawn('ktx', ['sl', query]);
let output = '';
ktx.stdout.on('data', (data) => {
output += data.toString();
});
ktx.on('close', (code) => {
if (code === 0) {
resolve(output);
} else {
reject(new Error(`ktx exited with code ${code}`));
}
});
});
}
// Usage
const revenueMetrics = await searchSemanticLayer('revenue');
console.log(revenueMetrics);import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
async function initKtxMcpClient() {
const transport = new StdioClientTransport({
command: 'ktx',
args: ['mcp', 'start', '--project-dir', process.cwd()]
});
const client = new Client({
name: 'my-data-agent',
version: '1.0.0'
}, {
capabilities: {}
});
await client.connect(transport);
return client;
}
async function searchMetrics(client: Client, query: string) {
const result = await client.callTool({
name: 'search_semantic_layer',
arguments: {
query,
limit: 10
}
});
return result;
}
// Usage
const client = await initKtxMcpClient();
const metrics = await searchMetrics(client, 'monthly revenue');
console.log(metrics);import subprocess
import json
def search_semantic_layer(query: str) -> dict:
"""Search ktx semantic layer via CLI."""
result = subprocess.run(
['ktx', 'sl', query, '--json'],
capture_output=True,
text=True,
check=True
)
return json.loads(result.stdout)
def get_metric_sql(metric_name: str) -> str:
"""Get canonical SQL for a metric."""
result = subprocess.run(
['ktx', 'semantic', 'show', metric_name, '--sql-only'],
capture_output=True,
text=True,
check=True
)
return result.stdout.strip()
# Usage
metrics = search_semantic_layer('revenue')
for metric in metrics.get('results', []):
print(f"{metric['name']}: {metric['description']}")
sql = get_metric_sql('monthly_revenue')
print(f"SQL:\n{sql}")semantic-layer/warehouse/revenue.yamltype: metric
name: monthly_revenue
description: Total revenue aggregated by month
sql: |
SELECT
DATE_TRUNC('month', order_date) as month,
SUM(amount) as revenue
FROM orders
WHERE status = 'completed'
GROUP BY 1
dimensions:
- month
- customer_segment
- region
measures:
- revenue
- order_count
grain: month
filters:
- status = 'completed'
- amount > 0
source_tables:
- orders
- customers# Navigate to project
cd /path/to/analytics-project
# Initialize ktx
ktx setup
# Configure database
ktx connection add warehouse \
--type postgres \
--host $DB_HOST \
--database analytics \
--user-env POSTGRES_USER \
--password-env POSTGRES_PASSWORD
# Add dbt context source
ktx context-source add dbt_models \
--type dbt \
--path ./dbt_project
# Build context
ktx ingest
# Verify
ktx status# Re-ingest to pick up schema changes
ktx ingest --connection warehouse
# Add a new wiki page about metric changes
ktx wiki create --title "Q1 Metric Updates" --content-file q1-updates.md
# Search to verify new content
ktx wiki "Q1 metric"Search ktx for customer retention metrics# List all semantic sources
ktx semantic list
# Show detailed metric definition
ktx semantic show monthly_revenue
# Validate metric SQL
ktx semantic validate monthly_revenue
# Check join paths
ktx semantic joins orders customersktx statusktx mcp start --project-dir /path/to/projectktx connection test warehousektx ingest --verbosektx ingest --exclude-tables table1,table2echo $ANTHROPIC_API_KEYktx config set llm.provider vertex
ktx ingestktx ingest --force --rebuild-embeddingsktx config get embeddings.provider
ktx config get embeddings.modelktx ingest --sample-size 1000type: entity
name: orders
primary_key: order_id
relationships:
- entity: customers
join_column: customer_id
relationship_type: many_to_onektx wiki search --contradictions-onlyktx wiki edit "Conflicting Metric Definition"ps aux | grep 'ktx mcp'ktx status --project-dir /path/to/projectANTHROPIC_API_KEYOPENAI_API_KEYPOSTGRES_USERPOSTGRES_PASSWORDSNOWFLAKE_ACCOUNTSNOWFLAKE_USERSNOWFLAKE_PASSWORDNOTION_API_KEYKTX_PROJECT_DIRktx.yamlconnections:
warehouse:
user_env: POSTGRES_USER
password_env: POSTGRES_PASSWORD