MCP Server
Beacon exposes a Model Context Protocol (MCP) server that lets AI assistants (Claude, Cursor, Windsurf, custom agents) query your data sources, search your catalog, and access documentation — all through a standardized protocol.
Table of contents
Overview
The MCP server is project-centric: each API key is scoped to one or more projects, and all tools automatically resolve which data sources, schemas, and documentation to use based on the active project.
What you can do through MCP:
- Ask natural language questions and get SQL + results back
- Execute direct SQL queries against any data source in your project
- Search tables, columns, and documentation by keyword
- Retrieve AI-generated documentation for your project, data sources, or individual tables
- Access project resources (schemas, quality reports, documentation)
Quick Start
1. Create an API Key
Go to API Keys in the React UI (/api-keys) and create a new key:
- Choose a scope:
Read,Execute, orAdmin - Optionally restrict to specific projects
- Copy the key — it’s shown only once (the key is SHA256-hashed before storage and never persisted in plaintext)
The key format is: sk-sem_...
2. Configure Your MCP Client
Add Beacon to your MCP client configuration. The exact format depends on your client.
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"beacon": {
"url": "https://your-beacon-host/beacon/mcp",
"headers": {
"Authorization": "Bearer sk-sem_YOUR_API_KEY"
}
}
}
}
Cursor (.cursor/mcp.json):
{
"mcpServers": {
"beacon": {
"url": "https://your-beacon-host/beacon/mcp",
"headers": {
"Authorization": "Bearer sk-sem_YOUR_API_KEY"
}
}
}
}
Windsurf (.windsurf/mcp.json):
{
"mcpServers": {
"beacon": {
"serverUrl": "https://your-beacon-host/beacon/mcp",
"headers": {
"Authorization": "Bearer sk-sem_YOUR_API_KEY"
}
}
}
}
3. Start Using It
Once connected, your AI assistant can use the tools described below. Try asking:
“What tables are available in my project?”
“How many orders were placed last week?”
“Show me the schema for the customers table”
Connection Details
| Property | Value |
|---|---|
| Endpoint | /beacon/mcp |
| Transport | Streamable HTTP + JSON-RPC 2.0 (via ModelContextProtocol.AspNetCore) |
| Authentication | Required — Authorization: Bearer sk-sem_... header |
The server is mounted with app.MapMcp("/beacon/mcp").RequireAuthorization(). Clients exchange JSON-RPC messages with the single /beacon/mcp endpoint over the Streamable HTTP transport; the server streams responses back on the same connection.
Tools
The MCP server exposes 5 tools that AI clients can call.
get_context
Get an overview of the project: data sources, schemas, tables, quality scores, and documentation status. This is the recommended starting point for understanding what data is available.
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
integer | No | Specify project if your API key has access to multiple projects |
Example response (markdown):
# Project: E-Commerce Analytics
2 data sources, 1 repository, documentation available
## Data Sources
### production-db (PostgreSQL)
- 45 tables, 3 schemas
- Quality: 87%
- Code references: 124
### analytics-api (REST API)
- 12 endpoints, 2 tags
ask
Ask a natural language question about your data. Beacon auto-detects the right data source(s), generates SQL, executes it, and returns results.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
question |
string | Yes | — | Natural language question (e.g., “How many orders were placed last week?”) |
project_id |
integer | No | — | Specify project if needed |
execute |
boolean | No | true |
Set to false to get the generated SQL without executing it |
How it works:
- Routing phase — The LLM determines which data source(s) to query (skipped for single-source projects)
- SQL generation — Generates SQL using your actual schema as context
- Execution — Runs the query with safety guardrails (read-only, row limits, PII detection)
Cross-source queries: If your question spans multiple data sources, Beacon queries each source separately and joins results in an in-memory SQLite database.
query
Execute a direct SQL query against a specific data source. Use this when you already know the exact query you want to run.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
datasource_name |
string | No* | — | Name of the data source |
datasource_id |
integer | No* | — | ID of the data source (alternative to name) |
sql |
string | No | — | SQL query (SELECT only) for database sources |
api_query |
string | No | — | JSON query definition for REST API sources |
max_rows |
integer | No | 100 |
Maximum rows to return (max: 1000) |
project_id |
integer | No | — | Specify project if needed |
*Either datasource_name or datasource_id is required.
For REST API data sources, pass a JSON query definition:
{
"method": "GET",
"path": "/api/users",
"parameters": { "limit": 10 },
"resultMapping": { ... }
}
get_documentation
Retrieve AI-generated documentation at three levels of detail.
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
integer | No | Specify project if needed |
datasource_name |
string | No | Get docs for a specific data source |
table_name |
string | No | Get detailed docs for a specific table or API endpoint |
schema_name |
string | No | Schema name or API tag (optional qualifier for table_name) |
Three levels:
- Project level (no parameters) — Full generated project documentation
- Data source level (
datasource_nameonly) — Tables, schemas, code references, quality scores - Table level (
table_name) — Columns with types, relationships, code references, quality rules, lineage
search
Search tables, columns, and documentation across all data sources in the project.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query |
string | Yes | — | Search keyword (e.g., “customer”, “order_date”, “revenue”) |
project_id |
integer | No | — | Specify project if needed |
max_results |
integer | No | 20 |
Maximum results to return (max: 50) |
Results include item type ([TABLE], [COLUMN], [DOC]), data source, description, and quality score.
Resources
The MCP server also exposes 4 resources per project that clients can read directly.
| Resource URI | Description |
|---|---|
beacon://project/{id}/documentation |
AI-generated project documentation (markdown) |
beacon://project/{id}/schema |
Full schema context across all data sources |
beacon://project/{id}/quality |
Data quality report with scores and trends |
beacon://project/{id}/report |
Comprehensive project report (sources, repos, stats) |
Safety & Guardrails
The MCP server enforces several safety measures:
| Feature | Description | Default |
|---|---|---|
| Read-only enforcement | Only SELECT queries are allowed |
Enabled |
| Row limits | Maximum rows returned per query | 100 (single), 500 (cross-source), max 1000 |
| PII detection | Automatically detects and flags sensitive data patterns | Enabled |
| Query timeout | Queries are cancelled after 30 seconds | Always on |
| Audit logging | Every tool call is recorded by McpAuditService with user, timing, and parameters |
Always on |
| Usage signals | Every tool call is recorded by McpSignalService to feed the learning loop |
Always on |
Both McpAuditService and McpSignalService fire on every tool invocation, including the failure path — they are never short-circuited.
SQL Accuracy Stack
Natural-language questions through the ask tool don’t go through a naive prompt-to-SQL pipe. Every generated query passes a layered accuracy stack:
- M-Schema grounding — the LLM context contains a structured schema rendering (column name, type, nullability, description) including real sample values from each column, so filters match actual data formats (
'shipped'vs'SHIPPED'). - AST read-only validation — generated SQL is parsed into an abstract syntax tree with a dialect-aware parser (PostgreSQL, SQL Server, MySQL, BigQuery, Snowflake, Databricks). DML/DDL statements, stacked queries, and comment-hidden writes are rejected before anything reaches your database — defense-in-depth beyond the regex guardrail.
- Dry-run repair loop — if execution fails, the SQL is retried with the database error and a refreshed schema context; truncated or degenerate repairs are rejected rather than executed.
- Row limits & PII masking — results are capped and sensitive values (emails, phone numbers, SSNs, credit cards, tokens, and custom regex patterns) are masked (
a***z) before leaving the server.
Learning Loop
The MCP server is self-improving. McpSignalService records a usage signal for every tool invocation (which questions were asked, which data sources and tables were used, whether execution succeeded). Recurring background jobs then process these signals:
- Pattern aggregation runs every 6 hours, consolidating recorded signals into learned query patterns that improve routing and SQL generation for the
asktool. - Signal cleanup runs daily, removing old signals to keep the learning store compact.
This loop runs entirely in the background and requires no configuration.
Configuration
Administrators can customize the MCP server behavior at MCP Settings in the React UI (/mcp-settings):
- Custom tool descriptions — Override the default description for each tool
- System prompt — Customize the LLM prompt used for SQL generation in the
asktool - Global instruction — Additional instructions injected into every
askrequest - Max row limit — Change the maximum rows returned (default: 1000)
- Read-only enforcement — Toggle SELECT-only restriction
- PII detection — Enable/disable and add custom PII regex patterns
These settings are part of Admin Settings; changes take effect without a restart.
MCP Playground
You don’t need to wire up an external MCP client to try the server. The React UI ships an MCP Playground (/mcp-playground) where you select a project and ask questions interactively — the same tools, routing, guardrails, and audit trail as a real MCP session. Use it to validate documentation quality and tune the system prompt before pointing Claude or Cursor at your data.
The companion MCP Learning page (/mcp-learning) shows the learning loop at work: usage signals, success rate, learned schema patterns awaiting approval, and proposed documentation patches you can apply or reject.
Manual Connection (Advanced)
If your MCP client doesn’t support Streamable HTTP configuration natively, you can drive the protocol manually by POSTing JSON-RPC messages to the single /beacon/mcp endpoint. Every request carries the Authorization: Bearer header.
Step 1: Initialize the Session
curl -X POST "https://your-host/beacon/mcp" \
-H "Authorization: Bearer sk-sem_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": { "name": "my-client", "version": "1.0" }
}
}'
Step 2: List Available Tools
curl -X POST "https://your-host/beacon/mcp" \
-H "Authorization: Bearer sk-sem_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}'
Step 3: Call a Tool
curl -X POST "https://your-host/beacon/mcp" \
-H "Authorization: Bearer sk-sem_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "get_context",
"arguments": {}
}
}'
The server streams the JSON-RPC response back on the same connection.
Troubleshooting
- “No project found” error
- Your API key must be associated with at least one project. Check API key settings.
- “Multiple projects available” error
- Your API key has access to multiple projects. Pass
project_idin your tool calls, or restrict the API key to a single project. - “Query validation failed” error
- The query contains write operations (INSERT, UPDATE, DELETE) which are blocked by read-only enforcement. Only SELECT queries are allowed.
- Connection drops or timeouts
- Streaming connections may be interrupted by proxies or load balancers. Reconnect by re-initializing against
/beacon/mcp— a fresh session will be created. - Authentication fails
- Verify your API key starts with
sk-sem_, hasn’t expired, and hasn’t been revoked. Check theAuthorization: Bearerheader format.