Skip to content

Chapter 27: MCP Dev Tools

1. What is MCP?

The Model Context Protocol connects AI coding tools to your running application. Claude Code, Cursor, and other assistants speak this protocol. When they connect, they see your database, routes, templates, and files -- not as static text, but as live, queryable tools.

Tina4 ships a built-in MCP server. It starts automatically in dev mode. No configuration needed.


2. How It Works

Set TINA4_DEBUG=true in your .env file and start the server:

bash
tina4 serve

The console prints:

MCP server available at http://localhost:7146/__dev/mcp

Tina4 writes the connection details to .claude/settings.json automatically. Claude Code discovers the server on its next restart. Cursor reads the same file.

Localhost-Only Security

The built-in MCP server activates only when two conditions hold:

  1. TINA4_DEBUG=true
  2. The server runs on localhost, 127.0.0.1, or 0.0.0.0

Deploy to a remote server and the MCP endpoint vanishes -- even with debug enabled. This prevents accidental exposure of database queries and file editing in production.

To enable on a staging server (rare, intentional), set:

bash
TINA4_MCP_REMOTE=true

3. Connecting AI Tools

Claude Code

Tina4 auto-generates .claude/settings.json:

json
{
  "mcpServers": {
    "tina4-dev": {
      "url": "http://localhost:7146/__dev/mcp/sse"
    }
  }
}

Restart Claude Code. It connects and lists the tools.

Cursor

Copy the same MCP config into Cursor's settings. The SSE URL is identical.

Manual Connection

Any MCP client can connect via:

  • SSE endpoint: GET http://localhost:7146/__dev/mcp/sse -- returns the message endpoint URL
  • Message endpoint: POST http://localhost:7146/__dev/mcp/message -- accepts JSON-RPC 2.0 messages

4. Built-in Tools

The MCP server exposes 48 tools organized by category. The exact list lives in tina4_python/mcp/tools.py -- the registration block at the bottom of that file is authoritative.

Database

ToolDescription
database_queryExecute a read-only SQL query (SELECT)
database_executeExecute arbitrary SQL (INSERT, UPDATE, DELETE, DDL)
database_tablesList all tables in the database
database_columnsGet column definitions for a specific table

Example -- an AI assistant queries your database directly:

Tool: database_query
Arguments: {"sql": "SELECT id, name, email FROM users WHERE active = 1"}

The database_execute tool handles write operations. It commits automatically after each statement.

Routes

ToolDescription
route_listList all registered routes with methods and auth status
route_testCall a route and return status, body, and headers
swagger_specReturn the full OpenAPI 3.0.3 specification

The route_test tool lets an AI assistant verify endpoints without leaving the conversation:

Tool: route_test
Arguments: {"method": "GET", "path": "/api/users"}

Templates

ToolDescription
template_renderRender a Frond template string with provided data

Useful for testing template snippets:

Tool: template_render
Arguments: {"template": "Hello {{ name }}!", "data": "{\"name\": \"Alice\"}"}

Files

ToolDescription
file_readRead a project file (relative to project root)
file_writeWrite or update a project file (full overwrite)
file_patchTargeted edit -- replace old_string with new_string in a file
file_listList files in a directory
asset_uploadUpload a file to src/public/

File operations are sandboxed. Paths that escape the project directory are rejected. An AI assistant cannot read /etc/passwd or write outside your project.

Migrations

ToolDescription
migration_statusList pending and completed migrations
migration_createCreate a new migration file
migration_runRun all pending migrations

Data and ORM

ToolDescription
orm_describeList all ORM models with fields, types, and relationships
seed_tableSeed a table with fake data

Infrastructure

ToolDescription
queue_statusQueue size by status (pending, completed, failed)
session_listActive sessions with data
cache_statsResponse cache hit/miss statistics

Debugging

ToolDescription
log_tailRead recent log entries
error_logRecent errors and exceptions with stack traces
env_listEnvironment variables (sensitive values redacted)
system_infoFramework version, Python version, project info

The env_list tool redacts any variable containing "secret", "password", "token", "key", or "credential" in its name.

Project introspection

ToolDescription
git_statusShow current branch, modified/untracked files, and recent commits
deps_listList the project's declared Python dependencies (from pyproject.toml)
project_overviewOne-shot snapshot: dependencies, routes, models, tables, errors, git

Persistent code index

ToolDescription
index_rebuildRefresh the persistent project index (lazy, mtime-based)
index_searchFind files by path, symbol, route, or summary -- use FIRST for "where is X"
index_fileFull index entry for one file: symbols, routes, imports
index_overviewProject shape: files by language, routes, models, recent edits

Framework documentation (prose)

ToolDescription
docs_listList framework documentation files
docs_searchSearch Tina4 framework docs for a query string -- use before guessing
docs_sectionReturn a full markdown section from a framework doc file

Live API RAG (reflection)

api_* tools query the live framework reflection -- actual class/method signatures, file/line locations, with a framework vs user source tag. Use these for "what's the signature of X?" questions; docs_* is for "explain queues conceptually".

ToolDescription
api_searchLive API search -- finds framework + user classes/methods by name/summary
api_classLive class reflection -- returns full method list and signatures for an FQN
api_methodLive method reflection -- returns signature, params, return type, file, line

Plan management

The plan_* family lets an AI assistant cooperate with a markdown plan file in plan/. Tina4 uses these to keep a steady record of in-progress refactors and multi-session work.

ToolDescription
plan_currentThe active plan: title, steps (done/not), next step, progress
plan_listAll plans in plan/ with progress and which one is active
plan_createCreate a new markdown plan and make it active
plan_switch_toMake a different plan the active one
plan_complete_stepTick a step as done (call the moment the step finishes)
plan_add_stepAppend a new unchecked step to the current plan
plan_noteAppend a timestamped note/breadcrumb to the current plan
plan_archiveMove a finished plan to plan/done/ and clear the current pointer
plan_readFull structured view of any plan by filename
plan_fleshAuto-generate concrete build steps via qwen and append them to a plan

5. Protocol Details

The MCP server uses JSON-RPC 2.0 over HTTP. Two endpoints serve the protocol:

SSE Endpoint (GET)

GET /__dev/mcp/sse
Content-Type: text/event-stream

Returns the message endpoint URL as a server-sent event:

event: endpoint
data: http://localhost:7146/__dev/mcp/message

Message Endpoint (POST)

POST /__dev/mcp/message
Content-Type: application/json

Accepts JSON-RPC 2.0 requests:

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}

Returns JSON-RPC 2.0 responses:

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {"name": "database_query", "description": "Execute a read-only SQL query", "inputSchema": {...}}
    ]
  }
}

Lifecycle

  1. Client sends initialize -- server responds with capabilities
  2. Client sends notifications/initialized -- server acknowledges
  3. Client calls tools/list -- server returns all registered tools with schemas
  4. Client calls tools/call with tool name and arguments -- server executes and returns results
  5. Client calls resources/list and resources/read for data resources

6. Troubleshooting

MCP server not starting:

  • Check TINA4_DEBUG=true in .env
  • Verify the server is running on localhost (not a remote host)

Claude Code not detecting the server:

  • Restart Claude Code after starting the Tina4 server
  • Check .claude/settings.json exists with the correct URL
  • Verify the port matches your server's port

Tools returning errors:

  • Database tools require orm_bind(db) in app.py
  • File tools are sandboxed to the project directory
  • database_execute only works on localhost

Remote server — MCP disabled:

  • This is intentional. Set TINA4_MCP_REMOTE=true only on staging environments you trust
  • Never enable MCP on production servers

Sponsored with 🩵 by Code InfinityCode Infinity