@papyruslabsai/seshat-mcp 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap.js +5 -2
- package/dist/graph.d.ts +5 -3
- package/dist/graph.js +6 -4
- package/dist/index.d.ts +9 -22
- package/dist/index.js +28 -41
- package/dist/loader.d.ts +1 -1
- package/dist/loader.js +3 -3
- package/dist/tools/functors.d.ts +5 -5
- package/dist/tools/functors.js +18 -18
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.js +11 -15
- package/dist/types.d.ts +12 -13
- package/dist/types.js +3 -4
- package/package.json +3 -3
package/dist/bootstrap.js
CHANGED
|
@@ -97,10 +97,13 @@ export async function bootstrap(projectDir) {
|
|
|
97
97
|
const projectName = inferProjectName(projectDir);
|
|
98
98
|
process.stderr.write(`[seshat-mcp] Auto-bootstrap: extracting ${projectName} from ${projectDir}\n`);
|
|
99
99
|
return new Promise((resolve) => {
|
|
100
|
-
// On Windows, npx is npx.cmd
|
|
100
|
+
// On Windows, npx is npx.cmd and must run through shell.
|
|
101
|
+
// shell: true concatenates args into a command string, so paths with
|
|
102
|
+
// spaces must be double-quoted to survive CMD parsing.
|
|
101
103
|
const isWindows = process.platform === 'win32';
|
|
102
104
|
const npxCmd = isWindows ? 'npx.cmd' : 'npx';
|
|
103
|
-
const
|
|
105
|
+
const q = (s) => isWindows && s.includes(' ') ? `"${s}"` : s;
|
|
106
|
+
const child = spawn(npxCmd, ['-y', '@papyruslabsai/seshat-extract', q(projectDir), q(seshatDir), projectName], {
|
|
104
107
|
cwd: projectDir,
|
|
105
108
|
shell: isWindows, // Windows needs shell: true for .cmd files
|
|
106
109
|
stdio: ['pipe', 'pipe', 'pipe'],
|
package/dist/graph.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Call Graph Construction & Blast Radius Computation
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Implements Theorem 9.4 (Incrementality):
|
|
4
|
+
* Computes the set of entities affected by a change:
|
|
6
5
|
* affected(e) = ancestors(e) ∪ descendants(e) ∪ {e}
|
|
6
|
+
*
|
|
7
|
+
* Ancestors = all transitive callers (upstream).
|
|
8
|
+
* Descendants = all transitive callees (downstream).
|
|
7
9
|
*/
|
|
8
10
|
import type { JstfEntity } from './types.js';
|
|
9
11
|
export interface CallGraph {
|
|
@@ -18,7 +20,7 @@ export interface BlastRadiusResult {
|
|
|
18
20
|
descendants: string[];
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
|
-
* Build a bidirectional call graph from entities'
|
|
23
|
+
* Build a bidirectional call graph from entities' dependency data.
|
|
22
24
|
*/
|
|
23
25
|
export declare function buildCallGraph(entities: JstfEntity[]): CallGraph;
|
|
24
26
|
/**
|
package/dist/graph.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Call Graph Construction & Blast Radius Computation
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Implements Theorem 9.4 (Incrementality):
|
|
4
|
+
* Computes the set of entities affected by a change:
|
|
6
5
|
* affected(e) = ancestors(e) ∪ descendants(e) ∪ {e}
|
|
6
|
+
*
|
|
7
|
+
* Ancestors = all transitive callers (upstream).
|
|
8
|
+
* Descendants = all transitive callees (downstream).
|
|
7
9
|
*/
|
|
8
10
|
/**
|
|
9
|
-
* Build a bidirectional call graph from entities'
|
|
11
|
+
* Build a bidirectional call graph from entities' dependency data.
|
|
10
12
|
*/
|
|
11
13
|
export function buildCallGraph(entities) {
|
|
12
14
|
const callers = new Map();
|
|
@@ -27,7 +29,7 @@ export function buildCallGraph(entities) {
|
|
|
27
29
|
entityByModule.get(mod).push(entity);
|
|
28
30
|
}
|
|
29
31
|
}
|
|
30
|
-
// Build call edges from
|
|
32
|
+
// Build call edges from dependency data
|
|
31
33
|
for (const caller of entities) {
|
|
32
34
|
if (!caller.id || !caller.edges?.calls)
|
|
33
35
|
continue;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @papyruslabs/seshat-mcp — Semantic MCP Server
|
|
3
|
+
* @papyruslabs/seshat-mcp — Semantic Code Analysis MCP Server
|
|
4
4
|
*
|
|
5
|
-
* Exposes a codebase's
|
|
6
|
-
* Reads .seshat/_bundle.json
|
|
5
|
+
* Exposes a codebase's structure, dependencies, and constraints as queryable
|
|
6
|
+
* MCP tools. Reads pre-extracted analysis data from .seshat/_bundle.json.
|
|
7
7
|
*
|
|
8
8
|
* Multi-project mode:
|
|
9
9
|
* Set SESHAT_PROJECTS env var to comma-separated paths or a glob pattern.
|
|
@@ -13,25 +13,12 @@
|
|
|
13
13
|
* Single-project mode (default):
|
|
14
14
|
* When SESHAT_PROJECTS is not set, loads from CWD. No `project` param needed.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
* list_projects
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* find_by_constraint — κ dimension search (AUTH, THROWS, DB_ACCESS, etc.)
|
|
23
|
-
* get_blast_radius — Theorem 9.4: affected set for given entity IDs
|
|
24
|
-
* list_modules — Group entities by layer, module, file, or language
|
|
25
|
-
* get_topology — API topology (routes, plugins, auth, tables)
|
|
26
|
-
* find_dead_code — Unreachable entities via ε-graph BFS
|
|
27
|
-
* find_layer_violations — ε edges violating architectural layer ordering
|
|
28
|
-
* get_coupling_metrics — Module coupling/cohesion/instability from ε-graph
|
|
29
|
-
* get_auth_matrix — Auth coverage across API-facing entities from κ
|
|
30
|
-
* find_error_gaps — Fallible callees whose callers lack try/catch
|
|
31
|
-
* get_test_coverage — Entities exercised by tests vs uncovered
|
|
32
|
-
* get_optimal_context — Greedy knapsack: max relevance per token for LLM context
|
|
33
|
-
* estimate_task_cost — Pre-work token burn projection from blast radius + source tokens
|
|
34
|
-
* report_actual_burn — Close calibration loop: actual tokens vs prediction, drift stats
|
|
16
|
+
* 18 tools across 3 categories:
|
|
17
|
+
* Discovery: list_projects, query_entities, get_entity, list_modules, get_topology
|
|
18
|
+
* Graph: get_dependencies, get_data_flow, find_by_constraint, get_blast_radius
|
|
19
|
+
* Analysis: find_dead_code, find_layer_violations, get_coupling_metrics,
|
|
20
|
+
* get_auth_matrix, find_error_gaps, get_test_coverage,
|
|
21
|
+
* get_optimal_context, estimate_task_cost, report_actual_burn
|
|
35
22
|
*
|
|
36
23
|
* Usage:
|
|
37
24
|
* npx @papyruslabs/seshat-mcp # single project (CWD)
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @papyruslabs/seshat-mcp — Semantic MCP Server
|
|
3
|
+
* @papyruslabs/seshat-mcp — Semantic Code Analysis MCP Server
|
|
4
4
|
*
|
|
5
|
-
* Exposes a codebase's
|
|
6
|
-
* Reads .seshat/_bundle.json
|
|
5
|
+
* Exposes a codebase's structure, dependencies, and constraints as queryable
|
|
6
|
+
* MCP tools. Reads pre-extracted analysis data from .seshat/_bundle.json.
|
|
7
7
|
*
|
|
8
8
|
* Multi-project mode:
|
|
9
9
|
* Set SESHAT_PROJECTS env var to comma-separated paths or a glob pattern.
|
|
@@ -13,25 +13,12 @@
|
|
|
13
13
|
* Single-project mode (default):
|
|
14
14
|
* When SESHAT_PROJECTS is not set, loads from CWD. No `project` param needed.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
* list_projects
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* find_by_constraint — κ dimension search (AUTH, THROWS, DB_ACCESS, etc.)
|
|
23
|
-
* get_blast_radius — Theorem 9.4: affected set for given entity IDs
|
|
24
|
-
* list_modules — Group entities by layer, module, file, or language
|
|
25
|
-
* get_topology — API topology (routes, plugins, auth, tables)
|
|
26
|
-
* find_dead_code — Unreachable entities via ε-graph BFS
|
|
27
|
-
* find_layer_violations — ε edges violating architectural layer ordering
|
|
28
|
-
* get_coupling_metrics — Module coupling/cohesion/instability from ε-graph
|
|
29
|
-
* get_auth_matrix — Auth coverage across API-facing entities from κ
|
|
30
|
-
* find_error_gaps — Fallible callees whose callers lack try/catch
|
|
31
|
-
* get_test_coverage — Entities exercised by tests vs uncovered
|
|
32
|
-
* get_optimal_context — Greedy knapsack: max relevance per token for LLM context
|
|
33
|
-
* estimate_task_cost — Pre-work token burn projection from blast radius + source tokens
|
|
34
|
-
* report_actual_burn — Close calibration loop: actual tokens vs prediction, drift stats
|
|
16
|
+
* 18 tools across 3 categories:
|
|
17
|
+
* Discovery: list_projects, query_entities, get_entity, list_modules, get_topology
|
|
18
|
+
* Graph: get_dependencies, get_data_flow, find_by_constraint, get_blast_radius
|
|
19
|
+
* Analysis: find_dead_code, find_layer_violations, get_coupling_metrics,
|
|
20
|
+
* get_auth_matrix, find_error_gaps, get_test_coverage,
|
|
21
|
+
* get_optimal_context, estimate_task_cost, report_actual_burn
|
|
35
22
|
*
|
|
36
23
|
* Usage:
|
|
37
24
|
* npx @papyruslabs/seshat-mcp # single project (CWD)
|
|
@@ -104,7 +91,7 @@ const TOOLS = [
|
|
|
104
91
|
},
|
|
105
92
|
{
|
|
106
93
|
name: 'query_entities',
|
|
107
|
-
description: 'Search entities
|
|
94
|
+
description: 'Search code entities by name, architectural layer (route/service/repository/component), module, or source language. Returns entity summaries with constraint tags.',
|
|
108
95
|
inputSchema: {
|
|
109
96
|
type: 'object',
|
|
110
97
|
properties: {
|
|
@@ -115,11 +102,11 @@ const TOOLS = [
|
|
|
115
102
|
},
|
|
116
103
|
layer: {
|
|
117
104
|
type: 'string',
|
|
118
|
-
description: 'Filter by
|
|
105
|
+
description: 'Filter by architectural layer: route, controller, service, repository, utility, hook, component, schema',
|
|
119
106
|
},
|
|
120
107
|
module: {
|
|
121
108
|
type: 'string',
|
|
122
|
-
description: 'Filter by
|
|
109
|
+
description: 'Filter by module (partial match)',
|
|
123
110
|
},
|
|
124
111
|
language: {
|
|
125
112
|
type: 'string',
|
|
@@ -134,7 +121,7 @@ const TOOLS = [
|
|
|
134
121
|
},
|
|
135
122
|
{
|
|
136
123
|
name: 'get_entity',
|
|
137
|
-
description: 'Get
|
|
124
|
+
description: 'Get complete details for a specific code entity. Returns structure, call graph, data flow, constraints, context, ownership, type info, runtime, and logic.',
|
|
138
125
|
inputSchema: {
|
|
139
126
|
type: 'object',
|
|
140
127
|
properties: {
|
|
@@ -149,7 +136,7 @@ const TOOLS = [
|
|
|
149
136
|
},
|
|
150
137
|
{
|
|
151
138
|
name: 'get_dependencies',
|
|
152
|
-
description: 'Traverse the
|
|
139
|
+
description: 'Traverse the call graph for an entity. Shows callers (who calls this), callees (what this calls), and imports. Supports depth-limited traversal for exploring transitive dependencies.',
|
|
153
140
|
inputSchema: {
|
|
154
141
|
type: 'object',
|
|
155
142
|
properties: {
|
|
@@ -173,7 +160,7 @@ const TOOLS = [
|
|
|
173
160
|
},
|
|
174
161
|
{
|
|
175
162
|
name: 'get_data_flow',
|
|
176
|
-
description: 'Get
|
|
163
|
+
description: 'Get data flow for an entity: what data flows in (inputs/sources), what flows out (outputs/returns), and what gets mutated (database writes, state changes).',
|
|
177
164
|
inputSchema: {
|
|
178
165
|
type: 'object',
|
|
179
166
|
properties: {
|
|
@@ -188,7 +175,7 @@ const TOOLS = [
|
|
|
188
175
|
},
|
|
189
176
|
{
|
|
190
177
|
name: 'find_by_constraint',
|
|
191
|
-
description: 'Search
|
|
178
|
+
description: 'Search entities by behavioral properties. Find functions by security properties (AUTH, VALIDATED), behavioral properties (PURE, THROWS, DB_ACCESS, NETWORK_IO), or performance characteristics.',
|
|
192
179
|
inputSchema: {
|
|
193
180
|
type: 'object',
|
|
194
181
|
properties: {
|
|
@@ -203,7 +190,7 @@ const TOOLS = [
|
|
|
203
190
|
},
|
|
204
191
|
{
|
|
205
192
|
name: 'get_blast_radius',
|
|
206
|
-
description: 'Compute the blast radius for a set of entities
|
|
193
|
+
description: 'Compute the blast radius for a set of entities. Returns all transitively affected entities — both upstream (callers) and downstream (callees) — with depth annotations showing distance from the change.',
|
|
207
194
|
inputSchema: {
|
|
208
195
|
type: 'object',
|
|
209
196
|
properties: {
|
|
@@ -219,7 +206,7 @@ const TOOLS = [
|
|
|
219
206
|
},
|
|
220
207
|
{
|
|
221
208
|
name: 'list_modules',
|
|
222
|
-
description: 'List and count entities grouped by a
|
|
209
|
+
description: 'List and count entities grouped by a property. See the architectural structure (by layer), module organization (by module), file distribution (by file), or language breakdown (by language).',
|
|
223
210
|
inputSchema: {
|
|
224
211
|
type: 'object',
|
|
225
212
|
properties: {
|
|
@@ -234,7 +221,7 @@ const TOOLS = [
|
|
|
234
221
|
},
|
|
235
222
|
{
|
|
236
223
|
name: 'get_topology',
|
|
237
|
-
description: 'Get the API topology: routes, plugins, auth patterns, and database tables. Built from
|
|
224
|
+
description: 'Get the API topology: routes, plugins, auth patterns, and database tables. Built from architectural context and dependency analysis across all entities.',
|
|
238
225
|
inputSchema: {
|
|
239
226
|
type: 'object',
|
|
240
227
|
properties: {
|
|
@@ -242,10 +229,10 @@ const TOOLS = [
|
|
|
242
229
|
},
|
|
243
230
|
},
|
|
244
231
|
},
|
|
245
|
-
// ───
|
|
232
|
+
// ─── Analysis Tools ─────────────────────────────────────────────
|
|
246
233
|
{
|
|
247
234
|
name: 'find_dead_code',
|
|
248
|
-
description: 'Find unreachable entities (dead code candidates). BFS from entry points (routes, exported functions, tests, plugins) through the
|
|
235
|
+
description: 'Find unreachable entities (dead code candidates). BFS from entry points (routes, exported functions, tests, plugins) through the call graph. Entities not reachable from any entry point are flagged.',
|
|
249
236
|
inputSchema: {
|
|
250
237
|
type: 'object',
|
|
251
238
|
properties: {
|
|
@@ -259,7 +246,7 @@ const TOOLS = [
|
|
|
259
246
|
},
|
|
260
247
|
{
|
|
261
248
|
name: 'find_layer_violations',
|
|
262
|
-
description: 'Detect architectural layer violations in the
|
|
249
|
+
description: 'Detect architectural layer violations in the call graph. Finds backward calls (lower layer calling higher layer, e.g. repository → route) and skip-layer calls (jumping over multiple layers). Uses architectural layer classification.',
|
|
263
250
|
inputSchema: {
|
|
264
251
|
type: 'object',
|
|
265
252
|
properties: {
|
|
@@ -269,7 +256,7 @@ const TOOLS = [
|
|
|
269
256
|
},
|
|
270
257
|
{
|
|
271
258
|
name: 'get_coupling_metrics',
|
|
272
|
-
description: 'Compute coupling, cohesion, and instability metrics for modules or layers. Analyzes
|
|
259
|
+
description: 'Compute coupling, cohesion, and instability metrics for modules or layers. Analyzes dependency edges between and within groups. High coupling + low cohesion = candidates for refactoring.',
|
|
273
260
|
inputSchema: {
|
|
274
261
|
type: 'object',
|
|
275
262
|
properties: {
|
|
@@ -284,7 +271,7 @@ const TOOLS = [
|
|
|
284
271
|
},
|
|
285
272
|
{
|
|
286
273
|
name: 'get_auth_matrix',
|
|
287
|
-
description: 'Analyze authentication coverage across all API-facing entities. Shows which routes/controllers have auth requirements
|
|
274
|
+
description: 'Analyze authentication coverage across all API-facing entities. Shows which routes/controllers have auth requirements and which don\'t. Detects inconsistencies like DB access without auth.',
|
|
288
275
|
inputSchema: {
|
|
289
276
|
type: 'object',
|
|
290
277
|
properties: {
|
|
@@ -294,7 +281,7 @@ const TOOLS = [
|
|
|
294
281
|
},
|
|
295
282
|
{
|
|
296
283
|
name: 'find_error_gaps',
|
|
297
|
-
description: 'Find error handling gaps:
|
|
284
|
+
description: 'Find error handling gaps: entities that throw or have network/db side effects whose callers lack try/catch. These are crash risk points where exceptions can propagate unhandled.',
|
|
298
285
|
inputSchema: {
|
|
299
286
|
type: 'object',
|
|
300
287
|
properties: {
|
|
@@ -304,7 +291,7 @@ const TOOLS = [
|
|
|
304
291
|
},
|
|
305
292
|
{
|
|
306
293
|
name: 'get_test_coverage',
|
|
307
|
-
description: 'Compute semantic test coverage: which production entities are exercised by test entities via the
|
|
294
|
+
description: 'Compute semantic test coverage: which production entities are exercised by test entities via the call graph. Optionally weight uncovered entities by blast radius to prioritize what to test first.',
|
|
308
295
|
inputSchema: {
|
|
309
296
|
type: 'object',
|
|
310
297
|
properties: {
|
|
@@ -454,7 +441,7 @@ async function main() {
|
|
|
454
441
|
}
|
|
455
442
|
const server = new Server({
|
|
456
443
|
name: serverLabel,
|
|
457
|
-
version: '0.4.
|
|
444
|
+
version: '0.4.2',
|
|
458
445
|
}, {
|
|
459
446
|
capabilities: {
|
|
460
447
|
tools: {},
|
|
@@ -516,7 +503,7 @@ async function main() {
|
|
|
516
503
|
case 'get_topology':
|
|
517
504
|
result = getTopology(args);
|
|
518
505
|
break;
|
|
519
|
-
//
|
|
506
|
+
// Analysis Tools
|
|
520
507
|
case 'find_dead_code':
|
|
521
508
|
result = findDeadCode(args);
|
|
522
509
|
break;
|
package/dist/loader.d.ts
CHANGED
package/dist/loader.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Bundle Loader
|
|
3
3
|
*
|
|
4
4
|
* Discovers and loads .seshat/_bundle.json from the current working directory.
|
|
5
5
|
* Falls back to checking common alternative locations.
|
|
@@ -28,8 +28,8 @@ export class BundleLoader {
|
|
|
28
28
|
const bundle = JSON.parse(raw);
|
|
29
29
|
this.entities = bundle.entities || [];
|
|
30
30
|
// Remap bundle field names to internal _ prefixed names.
|
|
31
|
-
// The extraction pipeline outputs `sourceFile`, `sourceLanguage
|
|
32
|
-
// but
|
|
31
|
+
// The extraction pipeline outputs `sourceFile`, `sourceLanguage`
|
|
32
|
+
// but the entity type expects `_sourceFile`, `_sourceLanguage`.
|
|
33
33
|
for (const e of this.entities) {
|
|
34
34
|
const raw = e;
|
|
35
35
|
if (raw.sourceFile && !e._sourceFile) {
|
package/dist/tools/functors.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Analysis Tools
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Composite analyses built from the extracted code entity graph.
|
|
5
|
+
* Each tool computes derived insights (dead code, layer violations,
|
|
6
|
+
* coupling metrics, auth coverage, etc.) from the entity data.
|
|
7
7
|
*/
|
|
8
8
|
import type { JstfEntity } from '../types.js';
|
|
9
9
|
/**
|
|
10
10
|
* Estimate the token cost of loading an entity's source code into an LLM context.
|
|
11
11
|
* Uses real sourceTokens from the extraction pipeline when available (v0.3.2+),
|
|
12
|
-
* falls back to heuristic estimation
|
|
12
|
+
* falls back to heuristic estimation for older bundles.
|
|
13
13
|
*/
|
|
14
14
|
export declare function estimateTokens(e: JstfEntity): number;
|
|
15
15
|
export declare function findDeadCode(args: {
|
package/dist/tools/functors.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Analysis Tools
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Composite analyses built from the extracted code entity graph.
|
|
5
|
+
* Each tool computes derived insights (dead code, layer violations,
|
|
6
|
+
* coupling metrics, auth coverage, etc.) from the entity data.
|
|
7
7
|
*/
|
|
8
8
|
import { computeBlastRadius } from '../graph.js';
|
|
9
9
|
import { getLoader, getGraph, validateProject, entityLayer, entitySummary, } from './index.js';
|
|
@@ -25,7 +25,7 @@ const LAYER_ORDER = {
|
|
|
25
25
|
/**
|
|
26
26
|
* Estimate the token cost of loading an entity's source code into an LLM context.
|
|
27
27
|
* Uses real sourceTokens from the extraction pipeline when available (v0.3.2+),
|
|
28
|
-
* falls back to heuristic estimation
|
|
28
|
+
* falls back to heuristic estimation for older bundles.
|
|
29
29
|
*/
|
|
30
30
|
export function estimateTokens(e) {
|
|
31
31
|
// Use real source token count from extraction pipeline
|
|
@@ -33,7 +33,7 @@ export function estimateTokens(e) {
|
|
|
33
33
|
const st = raw.sourceTokens;
|
|
34
34
|
if (st?.estimated)
|
|
35
35
|
return st.estimated;
|
|
36
|
-
// Fallback: heuristic
|
|
36
|
+
// Fallback: heuristic estimation (pre-v0.3.2 bundles)
|
|
37
37
|
let tokens = 50; // Base: name, id, layer
|
|
38
38
|
if (e.struct && typeof e.struct !== 'string') {
|
|
39
39
|
tokens += 20; // signature
|
|
@@ -53,7 +53,7 @@ export function estimateTokens(e) {
|
|
|
53
53
|
/**
|
|
54
54
|
* Detect which estimator was used for an entity.
|
|
55
55
|
* Returns 'syntactic' if tree-sitter leaf node count was used,
|
|
56
|
-
* 'charDiv4' if chars/4 heuristic was used, 'heuristic' for
|
|
56
|
+
* 'charDiv4' if chars/4 heuristic was used, 'heuristic' for legacy fallback.
|
|
57
57
|
*/
|
|
58
58
|
function detectEstimator(e) {
|
|
59
59
|
const raw = e;
|
|
@@ -80,7 +80,7 @@ function dominantEstimator(entities) {
|
|
|
80
80
|
return 'charDiv4';
|
|
81
81
|
return 'heuristic';
|
|
82
82
|
}
|
|
83
|
-
// ───
|
|
83
|
+
// ─── Tool: find_dead_code ────────────────────────────────────────
|
|
84
84
|
export function findDeadCode(args) {
|
|
85
85
|
const projErr = validateProject(args.project);
|
|
86
86
|
if (projErr)
|
|
@@ -150,7 +150,7 @@ export function findDeadCode(args) {
|
|
|
150
150
|
dead: deadEntities.slice(0, 100).map(entitySummary),
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
|
-
// ───
|
|
153
|
+
// ─── Tool: find_layer_violations ─────────────────────────────────
|
|
154
154
|
export function findLayerViolations(args) {
|
|
155
155
|
const projErr = validateProject(args?.project);
|
|
156
156
|
if (projErr)
|
|
@@ -206,7 +206,7 @@ export function findLayerViolations(args) {
|
|
|
206
206
|
violations: violations.slice(0, 100),
|
|
207
207
|
};
|
|
208
208
|
}
|
|
209
|
-
// ───
|
|
209
|
+
// ─── Tool: get_coupling_metrics ──────────────────────────────────
|
|
210
210
|
export function getCouplingMetrics(args) {
|
|
211
211
|
const projErr = validateProject(args.project);
|
|
212
212
|
if (projErr)
|
|
@@ -278,7 +278,7 @@ export function getCouplingMetrics(args) {
|
|
|
278
278
|
metrics: metrics.slice(0, 50),
|
|
279
279
|
};
|
|
280
280
|
}
|
|
281
|
-
// ───
|
|
281
|
+
// ─── Tool: get_auth_matrix ───────────────────────────────────────
|
|
282
282
|
export function getAuthMatrix(args) {
|
|
283
283
|
const projErr = validateProject(args?.project);
|
|
284
284
|
if (projErr)
|
|
@@ -336,7 +336,7 @@ export function getAuthMatrix(args) {
|
|
|
336
336
|
issues: inconsistencies.slice(0, 50),
|
|
337
337
|
};
|
|
338
338
|
}
|
|
339
|
-
// ───
|
|
339
|
+
// ─── Tool: find_error_gaps ───────────────────────────────────────
|
|
340
340
|
export function findErrorGaps(args) {
|
|
341
341
|
const projErr = validateProject(args?.project);
|
|
342
342
|
if (projErr)
|
|
@@ -349,13 +349,13 @@ export function findErrorGaps(args) {
|
|
|
349
349
|
for (const e of entities) {
|
|
350
350
|
if (!e.id)
|
|
351
351
|
continue;
|
|
352
|
-
// Check
|
|
352
|
+
// Check constraints.throws
|
|
353
353
|
const constraints = e.constraints;
|
|
354
354
|
if (constraints && !Array.isArray(constraints) && constraints.throws) {
|
|
355
355
|
fallibleIds.add(e.id);
|
|
356
356
|
continue;
|
|
357
357
|
}
|
|
358
|
-
// Check
|
|
358
|
+
// Check traits.self.fallible
|
|
359
359
|
const traits = e.traits;
|
|
360
360
|
if (traits && !Array.isArray(traits) && traits.self?.fallible) {
|
|
361
361
|
fallibleIds.add(e.id);
|
|
@@ -403,7 +403,7 @@ export function findErrorGaps(args) {
|
|
|
403
403
|
gaps: gaps.slice(0, 100),
|
|
404
404
|
};
|
|
405
405
|
}
|
|
406
|
-
// ───
|
|
406
|
+
// ─── Tool: get_test_coverage ─────────────────────────────────────
|
|
407
407
|
export function getTestCoverage(args) {
|
|
408
408
|
const projErr = validateProject(args.project);
|
|
409
409
|
if (projErr)
|
|
@@ -482,7 +482,7 @@ export function getTestCoverage(args) {
|
|
|
482
482
|
}
|
|
483
483
|
return result;
|
|
484
484
|
}
|
|
485
|
-
// ───
|
|
485
|
+
// ─── Tool: get_optimal_context ───────────────────────────────────
|
|
486
486
|
export function getOptimalContext(args) {
|
|
487
487
|
const projErr = validateProject(args.project);
|
|
488
488
|
if (projErr)
|
|
@@ -598,7 +598,7 @@ export function getOptimalContext(args) {
|
|
|
598
598
|
context: selected,
|
|
599
599
|
};
|
|
600
600
|
}
|
|
601
|
-
// ───
|
|
601
|
+
// ─── Tool: estimate_task_cost ────────────────────────────────────
|
|
602
602
|
/**
|
|
603
603
|
* Estimate token cost of a code change BEFORE starting work.
|
|
604
604
|
* Computes blast radius, sums source token counts, and projects total burn.
|
|
@@ -763,7 +763,7 @@ export async function estimateTaskCost(args) {
|
|
|
763
763
|
}
|
|
764
764
|
return result;
|
|
765
765
|
}
|
|
766
|
-
// ───
|
|
766
|
+
// ─── Tool: report_actual_burn ────────────────────────────────────
|
|
767
767
|
/**
|
|
768
768
|
* Close the calibration feedback loop by reporting actual token usage
|
|
769
769
|
* against a prior prediction from estimate_task_cost.
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Semantic MCP Tool Implementations
|
|
3
3
|
*
|
|
4
|
-
* Each tool exposes a
|
|
4
|
+
* Each tool exposes a query or computation over the extracted code entity graph.
|
|
5
5
|
* Tools operate on the in-memory entity bundle loaded from .seshat/_bundle.json.
|
|
6
6
|
*
|
|
7
7
|
* Multi-project: when multiple projects are loaded, each tool accepts an optional
|
package/dist/tools/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Semantic MCP Tool Implementations
|
|
3
3
|
*
|
|
4
|
-
* Each tool exposes a
|
|
4
|
+
* Each tool exposes a query or computation over the extracted code entity graph.
|
|
5
5
|
* Tools operate on the in-memory entity bundle loaded from .seshat/_bundle.json.
|
|
6
6
|
*
|
|
7
7
|
* Multi-project: when multiple projects are loaded, each tool accepts an optional
|
|
@@ -208,25 +208,21 @@ export function getEntity(args) {
|
|
|
208
208
|
if (!entity) {
|
|
209
209
|
return { error: `Entity not found: ${args.id}` };
|
|
210
210
|
}
|
|
211
|
-
// Return the full 9D coordinate dump
|
|
212
211
|
return {
|
|
213
212
|
id: entity.id,
|
|
214
213
|
name: entityName(entity),
|
|
215
214
|
...(entity._project ? { project: entity._project } : {}),
|
|
216
215
|
sourceFile: entity._sourceFile,
|
|
217
216
|
sourceLanguage: entity._sourceLanguage,
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
rho_runtime: entity.runtime,
|
|
228
|
-
sigma_semantics: entity.semantics,
|
|
229
|
-
},
|
|
217
|
+
structure: entity.struct,
|
|
218
|
+
call_graph: entity.edges,
|
|
219
|
+
data_flow: entity.data,
|
|
220
|
+
constraints: entity.constraints,
|
|
221
|
+
context: entity.context,
|
|
222
|
+
ownership: entity.ownership,
|
|
223
|
+
type_info: entity.traits,
|
|
224
|
+
runtime: entity.runtime,
|
|
225
|
+
logic: entity.semantics,
|
|
230
226
|
};
|
|
231
227
|
}
|
|
232
228
|
// ─── Tool: get_dependencies ───────────────────────────────────────
|
|
@@ -258,7 +254,7 @@ export function getDependencies(args) {
|
|
|
258
254
|
return e ? entitySummary(e) : { id: cId };
|
|
259
255
|
});
|
|
260
256
|
}
|
|
261
|
-
// Also include direct imports
|
|
257
|
+
// Also include direct imports
|
|
262
258
|
if (entity.edges?.imports) {
|
|
263
259
|
result.imports = entity.edges.imports;
|
|
264
260
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Code Entity — the core unit of analysis
|
|
3
3
|
*
|
|
4
4
|
* Each entity represents a code unit (function, class, module, schema)
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* χ (context), λ (ownership), τ (traits), ρ (runtime), Σ (semantics)
|
|
5
|
+
* with extracted properties: structure, call graph, data flow, constraints,
|
|
6
|
+
* context, ownership, type info, runtime, and logic.
|
|
8
7
|
*/
|
|
9
8
|
export interface JstfEntity {
|
|
10
9
|
id: string;
|
|
@@ -12,7 +11,7 @@ export interface JstfEntity {
|
|
|
12
11
|
_sourceFile?: string | null;
|
|
13
12
|
_sourceLanguage?: string;
|
|
14
13
|
_project?: string;
|
|
15
|
-
/**
|
|
14
|
+
/** Structure: function shape, signature, modifiers */
|
|
16
15
|
struct?: {
|
|
17
16
|
name?: string;
|
|
18
17
|
type?: string;
|
|
@@ -25,7 +24,7 @@ export interface JstfEntity {
|
|
|
25
24
|
returnType?: string;
|
|
26
25
|
[key: string]: unknown;
|
|
27
26
|
} | string;
|
|
28
|
-
/**
|
|
27
|
+
/** Call graph: dependencies, imports, callers */
|
|
29
28
|
edges?: {
|
|
30
29
|
calls?: Array<{
|
|
31
30
|
target: string;
|
|
@@ -41,7 +40,7 @@ export interface JstfEntity {
|
|
|
41
40
|
}>;
|
|
42
41
|
[key: string]: unknown;
|
|
43
42
|
};
|
|
44
|
-
/**
|
|
43
|
+
/** Data flow: inputs, outputs, mutations */
|
|
45
44
|
data?: {
|
|
46
45
|
inputs?: Array<{
|
|
47
46
|
name: string;
|
|
@@ -61,7 +60,7 @@ export interface JstfEntity {
|
|
|
61
60
|
returns?: unknown[];
|
|
62
61
|
[key: string]: unknown;
|
|
63
62
|
};
|
|
64
|
-
/**
|
|
63
|
+
/** Constraints: behavioral contracts, validation, purity */
|
|
65
64
|
constraints?: {
|
|
66
65
|
security?: string[];
|
|
67
66
|
performance?: Record<string, unknown>;
|
|
@@ -82,7 +81,7 @@ export interface JstfEntity {
|
|
|
82
81
|
};
|
|
83
82
|
[key: string]: unknown;
|
|
84
83
|
} | string[];
|
|
85
|
-
/**
|
|
84
|
+
/** Context: architectural position, visibility, layer */
|
|
86
85
|
context?: {
|
|
87
86
|
layer?: string;
|
|
88
87
|
layerSource?: string;
|
|
@@ -94,9 +93,9 @@ export interface JstfEntity {
|
|
|
94
93
|
criticality?: string;
|
|
95
94
|
[key: string]: unknown;
|
|
96
95
|
};
|
|
97
|
-
/**
|
|
96
|
+
/** Ownership: memory management, lifetimes, borrowing (Rust/C++) */
|
|
98
97
|
ownership?: Record<string, unknown>;
|
|
99
|
-
/**
|
|
98
|
+
/** Type info: type capabilities, bounds, markers */
|
|
100
99
|
traits?: string[] | {
|
|
101
100
|
self?: {
|
|
102
101
|
asyncContext?: boolean;
|
|
@@ -109,14 +108,14 @@ export interface JstfEntity {
|
|
|
109
108
|
}>;
|
|
110
109
|
[key: string]: unknown;
|
|
111
110
|
};
|
|
112
|
-
/**
|
|
111
|
+
/** Runtime: async model, platform, framework */
|
|
113
112
|
runtime?: {
|
|
114
113
|
async?: string;
|
|
115
114
|
framework?: string;
|
|
116
115
|
platform?: string;
|
|
117
116
|
[key: string]: unknown;
|
|
118
117
|
};
|
|
119
|
-
/**
|
|
118
|
+
/** Logic: operational content, normalized logic tree */
|
|
120
119
|
semantics?: unknown[];
|
|
121
120
|
[key: string]: unknown;
|
|
122
121
|
}
|
package/dist/types.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Code Entity — the core unit of analysis
|
|
3
3
|
*
|
|
4
4
|
* Each entity represents a code unit (function, class, module, schema)
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* χ (context), λ (ownership), τ (traits), ρ (runtime), Σ (semantics)
|
|
5
|
+
* with extracted properties: structure, call graph, data flow, constraints,
|
|
6
|
+
* context, ownership, type info, runtime, and logic.
|
|
8
7
|
*/
|
|
9
8
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@papyruslabsai/seshat-mcp",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "Semantic MCP server — exposes a codebase's
|
|
3
|
+
"version": "0.4.2",
|
|
4
|
+
"description": "Semantic MCP server — exposes a codebase's structure, dependencies, and constraints as queryable tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"seshat-mcp": "./dist/index.js"
|
|
@@ -30,6 +30,6 @@
|
|
|
30
30
|
"url": "https://github.com/papyruslabs-ai/seshat.git",
|
|
31
31
|
"directory": "packages/seshat-mcp"
|
|
32
32
|
},
|
|
33
|
-
"keywords": ["mcp", "
|
|
33
|
+
"keywords": ["mcp", "semantic", "code-analysis", "seshat", "static-analysis"],
|
|
34
34
|
"license": "MIT"
|
|
35
35
|
}
|