Class: DatabaseManifestResource

Inherits:
Object
  • Object
show all
Defined in:
app/mcp/database_manifest_resource.rb

Overview

Builds MCP Resources that expose database schema manifests to external clients
(Claude Desktop, Cursor, etc.) so they can discover available tables/views
without making multiple tool calls.

Resources:
db://app_db/manifest — Summary of all analytics views and reference tables
db://versions/manifest — Summary of audit trail tables
db://app_db/tables/name — Detailed schema for a specific table/view

The app_db manifest reads from Assistant::CommentManifest (YAML-backed)
with column types introspected from pg_attribute at runtime.
The versions manifest is built dynamically from pg_tables.

Access control: the resources_read_handler checks Thread.current[:mcp_auth_result]
for the appropriate service key (app_db or postgres_versions).

Constant Summary collapse

SERVICE_KEY_MAP =

Maps resource URIs to their required service key for access control.

{
  'db://app_db/manifest' => 'app_db',
  'db://versions/manifest' => 'postgres_versions'
}.freeze

Class Method Summary collapse

Class Method Details

.build_resource_templatesArray<MCP::ResourceTemplate>

Build a ResourceTemplate for per-table detail lookups.

Returns:

  • (Array<MCP::ResourceTemplate>)


45
46
47
48
49
50
51
52
53
54
55
# File 'app/mcp/database_manifest_resource.rb', line 45

def self.build_resource_templates
  [
    MCP::ResourceTemplate.new(
      uri_template: 'db://app_db/tables/{table_name}',
      name: 'app-db-table-detail',
      description: 'Detailed schema for a specific table or view in the app database. ' \
                   'Returns columns with types, descriptions, tips, and indexes.',
      mime_type: 'application/json'
    )
  ]
end

.build_resourcesArray<MCP::Resource>

Build static MCP::Resource entries for each database manifest.

Returns:

  • (Array<MCP::Resource>)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'app/mcp/database_manifest_resource.rb', line 24

def self.build_resources
  [
    MCP::Resource.new(
      uri: 'db://app_db/manifest',
      name: 'app-db-manifest',
      description: 'Schema manifest for the application database. ' \
                   'Lists all analytics views and reference tables with descriptions and column counts.',
      mime_type: 'application/json'
    ),
    MCP::Resource.new(
      uri: 'db://versions/manifest',
      name: 'versions-db-manifest',
      description: 'Schema manifest for the audit trail / versions database. ' \
                   'Lists all tables with column counts.',
      mime_type: 'application/json'
    )
  ]
end

.read(uri) ⇒ Array<Hash>

Handle a resources/read request. Returns an array of content hashes.

Parameters:

  • uri (String)

    The resource URI being read

Returns:

  • (Array<Hash>)

    MCP resource content response



66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'app/mcp/database_manifest_resource.rb', line 66

def self.read(uri)
  case uri
  when 'db://app_db/manifest'
    read_app_db_manifest(uri)
  when 'db://versions/manifest'
    read_versions_manifest(uri)
  when %r{\Adb://app_db/tables/(.+)\z}
    table_name = Regexp.last_match(1)
    read_app_db_table_detail(uri, table_name)
  else
    [{ uri: uri, mimeType: 'text/plain', text: "Unknown resource: #{uri}" }]
  end
end