@papyruslabsai/seshat-mcp 0.13.2 → 0.13.4

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/index.js CHANGED
@@ -25,6 +25,7 @@ Use Seshat tools instead of grep/Read when you need to understand code structure
25
25
  - "What breaks if I change this?" → get_blast_radius
26
26
  - "What data does this read/write/mutate?" → get_data_flow
27
27
  - "Which functions touch the DB / require auth / throw?" → find_by_constraint
28
+ - "What reads or writes the 'users' table?" → find_by_constraint(table="users")
28
29
  - "Which endpoints require auth and which don't?" → get_auth_matrix
29
30
  - "Where is sensitive data exposed without protection?" → find_exposure_leaks
30
31
  - "What should I read before modifying X?" → get_optimal_context
@@ -33,7 +34,7 @@ Use Seshat tools instead of grep/Read when you need to understand code structure
33
34
  All tools are read-only and safe to call speculatively — there is no cost to trying them.
34
35
 
35
36
  get_blast_radius and get_optimal_context are designed to be called iteratively. Start with any entity, then feed discovered entities back in to expand your understanding. Each round reveals new structure that informs where to look next. When answering "what does this system do?" questions, a few rounds of blast_radius → get_entity → blast_radius on the newly discovered symbols will build a complete picture faster than reading files.`;
36
- const TIER_ORDER = ['cartographer', 'analyst', 'architect'];
37
+ const TIER_ORDER = ['cartographer', 'pro', 'analyst', 'architect', 'founder'];
37
38
  const TOOL_TIERS = {
38
39
  // Cartographer (free) — explore, navigate, and assess security surface
39
40
  list_projects: 'cartographer',
@@ -68,8 +69,10 @@ const TOOL_TIERS = {
68
69
  };
69
70
  const TIER_LABELS = {
70
71
  cartographer: 'Cartographer (Free)',
71
- analyst: 'Analyst (Tier 2)',
72
- architect: 'Architect (Tier 3)',
72
+ pro: 'Seshat Pro',
73
+ analyst: 'Seshat Shield',
74
+ architect: 'Architect',
75
+ founder: 'Founder (All Access)',
73
76
  };
74
77
  function tierAtLeast(userTier, requiredTier) {
75
78
  return TIER_ORDER.indexOf(userTier) >= TIER_ORDER.indexOf(requiredTier);
@@ -118,7 +121,7 @@ const TOOLS = [
118
121
  },
119
122
  {
120
123
  name: 'get_entity',
121
- description: 'Get everything about one function or class — its signature, callers, callees, data flow, constraints, and source location. Use this when you need to deeply understand a single symbol before modifying it. Returns more than reading the source file because it includes the dependency context.',
124
+ description: 'Get everything about one function or class — its signature, callers, callees, data flow, constraints, source location, and database operations (which tables it reads/writes). Use this when you need to deeply understand a single symbol before modifying it. Returns more than reading the source file because it includes the dependency context.',
122
125
  inputSchema: {
123
126
  type: 'object',
124
127
  properties: {
@@ -159,12 +162,13 @@ const TOOLS = [
159
162
  },
160
163
  {
161
164
  name: 'find_by_constraint',
162
- description: 'Find every function with a specific behavior tag — AUTH (requires authentication), DB_ACCESS (touches database), THROWS (can throw), PURE (no side effects), NETWORK_IO (makes HTTP calls), VALIDATED (has input validation). Use this when you need to answer questions like "which functions write to the database?" or "what endpoints lack auth?"',
165
+ description: 'Find every function with a specific syntactic constraint tag — AUTH (requires authentication), DB_ACCESS (touches database), THROWS (explicit throw statement), PURE (no side effects), NETWORK_IO (makes HTTP calls), VALIDATED (has input validation). Also supports table-level queries: pass table="walks" to find every function that reads or writes the walks table (answers "what touches this table?" for schema migrations). Constraints are extracted from source syntax, not inferred. For semantic/behavioral properties (e.g., "can fail transitively"), use query_traits instead.',
163
166
  inputSchema: {
164
167
  type: 'object',
165
168
  properties: {
166
169
  project: projectParam,
167
170
  constraint: { type: 'string', description: 'Constraint tag to search for: AUTH, VALIDATED, PURE, THROWS, DB_ACCESS, NETWORK_IO, IMP, etc.' },
171
+ table: { type: 'string', description: 'Optional: filter to functions that touch a specific database table (e.g., "walks", "users"). Returns structured db_operations showing read/write/mutate per function.' },
168
172
  },
169
173
  required: ['constraint'],
170
174
  },
@@ -243,7 +247,7 @@ const TOOLS = [
243
247
  },
244
248
  {
245
249
  name: 'get_coupling_metrics',
246
- description: 'Measure how tangled modules are. Returns coupling (cross-module dependencies), cohesion (within-module dependencies), and instability scores. High coupling + low cohesion = refactoring candidates. Use this when planning a refactor to find the worst offenders.',
250
+ description: 'Measure how tangled your code is. Returns coupling (cross-boundary dependencies), cohesion (within-group dependencies), and instability scores. High coupling + low cohesion = refactoring candidates. Start with group_by: "layer" for the architectural health view ("are my controllers more coupled than my services?"), then drill into group_by: "module" for specific hotspots.',
247
251
  inputSchema: {
248
252
  type: 'object',
249
253
  properties: {
@@ -285,19 +289,19 @@ const TOOLS = [
285
289
  },
286
290
  {
287
291
  name: 'find_runtime_violations',
288
- description: 'Find architectural boundary leaks where framework-agnostic code imports framework-specific code. Use this when separating core logic from framework dependencies.',
292
+ description: 'Find architectural boundary leaks where framework-agnostic code imports framework-specific code. Use this when separating core logic from framework dependencies. Returns 0 for most JS/Python codebases — a non-zero result indicates a serious boundary violation worth investigating.',
289
293
  inputSchema: { type: 'object', properties: { project: projectParam } },
290
294
  annotations: READ_ONLY_OPEN,
291
295
  },
292
296
  {
293
297
  name: 'find_ownership_violations',
294
- description: 'Find memory and lifecycle issues — entities with complex ownership, unsafe blocks, escaping references, or illegal mutability on borrowed data. Most useful for Rust and C++ codebases.',
298
+ description: 'Find memory and lifecycle issues — entities with complex ownership, unsafe blocks, escaping references, or illegal mutability on borrowed data. Returns 0 for most JS/Python codebases — a non-zero result in those languages indicates a serious boundary violation worth investigating. Most detailed results for Rust and C++.',
295
299
  inputSchema: { type: 'object', properties: { project: projectParam } },
296
300
  annotations: READ_ONLY_OPEN,
297
301
  },
298
302
  {
299
303
  name: 'query_traits',
300
- description: 'Find functions by abstract capability regardless of syntax — "fallible" (can fail), "asyncContext" (carries async state), "generator" (yields values). Use this when you need to find all code with a specific behavioral trait across the entire codebase.',
304
+ description: 'Find functions by inferred behavioral trait — "fallible" (can fail, including transitively via callees that throw), "asyncContext" (carries async state), "generator" (yields values). Traits are semantic properties inferred from the call graph, not just syntax. Use this when you need to find all code with a specific capability. For syntactic tags (explicit throw statements, DB access), use find_by_constraint instead.',
301
305
  inputSchema: {
302
306
  type: 'object',
303
307
  properties: {
@@ -469,7 +473,7 @@ function getCloudUrl(path) {
469
473
  async function main() {
470
474
  const server = new Server({
471
475
  name: 'seshat',
472
- version: '0.13.2',
476
+ version: '0.13.4',
473
477
  }, {
474
478
  capabilities: { tools: {} },
475
479
  instructions: SERVER_INSTRUCTIONS,
@@ -135,6 +135,15 @@ export function findDeadCode(args, loader) {
135
135
  if (!include_tests) {
136
136
  deadEntities = deadEntities.filter((e) => entityLayer(e) !== 'test');
137
137
  }
138
+ // Separate schemas — they're often registered dynamically (e.g., fastify.addSchema())
139
+ // and appear "dead" from a static call graph but are alive at runtime.
140
+ const SCHEMA_TYPES = new Set(['schema', 'typealias', 'interface', 'type']);
141
+ const schemaEntities = deadEntities.filter((e) => {
142
+ const type = (typeof e.struct === 'string' ? e.struct : e.struct?.type || '').toLowerCase();
143
+ const layer = entityLayer(e);
144
+ return SCHEMA_TYPES.has(type) || layer === 'schema';
145
+ });
146
+ deadEntities = deadEntities.filter((e) => !schemaEntities.includes(e));
138
147
  // Group by layer for overview
139
148
  const byLayer = new Map();
140
149
  for (const e of deadEntities) {
@@ -148,6 +157,10 @@ export function findDeadCode(args, loader) {
148
157
  deadCount: deadEntities.length,
149
158
  deadByLayer: Object.fromEntries([...byLayer.entries()].sort((a, b) => b[1] - a[1])),
150
159
  dead: deadEntities.slice(0, 100).map(entitySummary),
160
+ ...(schemaEntities.length > 0 ? {
161
+ schemas_excluded: schemaEntities.length,
162
+ _note_schemas: `${schemaEntities.length} schema/type definitions excluded — no static references found, but schemas are often registered dynamically (e.g., fastify.addSchema()) and may be alive at runtime.`,
163
+ } : {}),
151
164
  };
152
165
  }
153
166
  // ─── Tool: find_layer_violations ─────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@papyruslabsai/seshat-mcp",
3
- "version": "0.13.2",
3
+ "version": "0.13.4",
4
4
  "description": "Semantic MCP server — exposes a codebase's structure, dependencies, and constraints as queryable tools",
5
5
  "type": "module",
6
6
  "bin": {