coaiajs 0.1.0
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/CLAUDE.md +56 -0
- package/KINSHIP.md +63 -0
- package/README.md +148 -0
- package/articles/academic/creative-orientation-vs-problem-solving.md +177 -0
- package/articles/academic/jsonl-knowledge-graphs-agent-memory.md +142 -0
- package/articles/academic/langfuse-observability-llm-pipelines.md +144 -0
- package/articles/academic/medicine-wheel-software-architecture.md +163 -0
- package/articles/academic/mmot-autonomous-agents.md +156 -0
- package/articles/academic/model-context-protocol-interagent.md +161 -0
- package/articles/academic/pde-prompt-decomposition.md +186 -0
- package/articles/academic/structural-tension-in-ai-agents.md +134 -0
- package/articles/reviews/mcp-protocol-design-review.md +170 -0
- package/articles/reviews/observability-ai-systems-review.md +176 -0
- package/articles/reviews/prompt-engineering-decomposition-review.md +184 -0
- package/articles/surveys/agent-orchestration-survey.md +186 -0
- package/articles/surveys/knowledge-graph-storage-survey.md +204 -0
- package/articles/surveys/structural-tension-methodology-survey.md +154 -0
- package/articles/technical/aws-sdk-v3-polly.md +270 -0
- package/articles/technical/commander-cli-framework.md +262 -0
- package/articles/technical/dotenv-config-patterns.md +360 -0
- package/articles/technical/ioredis-vs-redis.md +142 -0
- package/articles/technical/langfuse-js-sdk-vs-rest.md +191 -0
- package/articles/technical/mcp-sdk-typescript.md +291 -0
- package/articles/technical/octokit-github-api.md +293 -0
- package/articles/technical/openai-sdk-modern.md +231 -0
- package/articles/technical/yaml-parsing-node.md +266 -0
- package/articles/technical/zod-runtime-validation.md +212 -0
- package/dist/mcp/config.d.ts +14 -0
- package/dist/mcp/config.js +185 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.js +324 -0
- package/dist/mcp/tools/coaiapy-tools.d.ts +8 -0
- package/dist/mcp/tools/coaiapy-tools.js +326 -0
- package/dist/mcp/tools/index.d.ts +3 -0
- package/dist/mcp/tools/index.js +3 -0
- package/dist/src/audio.d.ts +12 -0
- package/dist/src/audio.js +57 -0
- package/dist/src/cli-helpers.d.ts +9 -0
- package/dist/src/cli-helpers.js +78 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.js +1086 -0
- package/dist/src/config.d.ts +15 -0
- package/dist/src/config.js +145 -0
- package/dist/src/environment.d.ts +44 -0
- package/dist/src/environment.js +146 -0
- package/dist/src/github.d.ts +47 -0
- package/dist/src/github.js +79 -0
- package/dist/src/langfuse/client.d.ts +30 -0
- package/dist/src/langfuse/client.js +75 -0
- package/dist/src/langfuse/comments.d.ts +16 -0
- package/dist/src/langfuse/comments.js +36 -0
- package/dist/src/langfuse/datasets.d.ts +19 -0
- package/dist/src/langfuse/datasets.js +140 -0
- package/dist/src/langfuse/index.d.ts +13 -0
- package/dist/src/langfuse/index.js +10 -0
- package/dist/src/langfuse/media.d.ts +11 -0
- package/dist/src/langfuse/media.js +167 -0
- package/dist/src/langfuse/observations.d.ts +18 -0
- package/dist/src/langfuse/observations.js +113 -0
- package/dist/src/langfuse/prompts.d.ts +14 -0
- package/dist/src/langfuse/prompts.js +127 -0
- package/dist/src/langfuse/scores.d.ts +54 -0
- package/dist/src/langfuse/scores.js +366 -0
- package/dist/src/langfuse/traces.d.ts +29 -0
- package/dist/src/langfuse/traces.js +225 -0
- package/dist/src/llm.d.ts +23 -0
- package/dist/src/llm.js +76 -0
- package/dist/src/narrative/graph-manager.d.ts +106 -0
- package/dist/src/narrative/graph-manager.js +915 -0
- package/dist/src/narrative/index.d.ts +9 -0
- package/dist/src/narrative/index.js +7 -0
- package/dist/src/narrative/markdown-export.d.ts +21 -0
- package/dist/src/narrative/markdown-export.js +383 -0
- package/dist/src/narrative/tool-definitions.d.ts +21 -0
- package/dist/src/narrative/tool-definitions.js +588 -0
- package/dist/src/narrative/tool-handlers.d.ts +11 -0
- package/dist/src/narrative/tool-handlers.js +462 -0
- package/dist/src/narrative/types.d.ts +2 -0
- package/dist/src/narrative/types.js +2 -0
- package/dist/src/narrative/validation.d.ts +29 -0
- package/dist/src/narrative/validation.js +144 -0
- package/dist/src/pde/index.d.ts +8 -0
- package/dist/src/pde/index.js +8 -0
- package/dist/src/pde/mcp-handlers.d.ts +7 -0
- package/dist/src/pde/mcp-handlers.js +300 -0
- package/dist/src/pde/mcp-tools.d.ts +15 -0
- package/dist/src/pde/mcp-tools.js +191 -0
- package/dist/src/pde/session-manager.d.ts +32 -0
- package/dist/src/pde/session-manager.js +205 -0
- package/dist/src/pde/stc-mapper.d.ts +26 -0
- package/dist/src/pde/stc-mapper.js +234 -0
- package/dist/src/pipeline/index.d.ts +2 -0
- package/dist/src/pipeline/index.js +3 -0
- package/dist/src/pipeline/template-engine.d.ts +20 -0
- package/dist/src/pipeline/template-engine.js +361 -0
- package/dist/src/planning/index.d.ts +7 -0
- package/dist/src/planning/index.js +7 -0
- package/dist/src/planning/mcp-handlers.d.ts +7 -0
- package/dist/src/planning/mcp-handlers.js +310 -0
- package/dist/src/planning/mcp-tools.d.ts +15 -0
- package/dist/src/planning/mcp-tools.js +145 -0
- package/dist/src/planning/plan-parser.d.ts +35 -0
- package/dist/src/planning/plan-parser.js +506 -0
- package/dist/src/redis.d.ts +21 -0
- package/dist/src/redis.js +78 -0
- package/dist/src/types.d.ts +244 -0
- package/dist/src/types.js +8 -0
- package/mcp/config.ts +196 -0
- package/mcp/server.ts +402 -0
- package/mcp/tools/coaiapy-tools.ts +364 -0
- package/mcp/tools/index.ts +4 -0
- package/package.json +52 -0
- package/rispecs/00-coaiajs-platform.spec.md +102 -0
- package/rispecs/01-core-config.spec.md +89 -0
- package/rispecs/02-redis-module.spec.md +62 -0
- package/rispecs/03-langfuse-module.spec.md +101 -0
- package/rispecs/04-narrative-engine.spec.md +185 -0
- package/rispecs/05-pde-engine.spec.md +112 -0
- package/rispecs/06-planning-engine.spec.md +128 -0
- package/rispecs/07-pipeline-templates.spec.md +97 -0
- package/rispecs/08-cli-interface.spec.md +134 -0
- package/rispecs/09-mcp-server.spec.md +140 -0
- package/rispecs/10-audio-module.spec.md +63 -0
- package/rispecs/KINSHIP.md +56 -0
- package/rispecs/README.md +100 -0
- package/src/audio.ts +76 -0
- package/src/cli-helpers.ts +86 -0
- package/src/cli.ts +1223 -0
- package/src/config.ts +172 -0
- package/src/environment.ts +171 -0
- package/src/github.ts +143 -0
- package/src/langfuse/client.ts +105 -0
- package/src/langfuse/comments.ts +52 -0
- package/src/langfuse/datasets.ts +178 -0
- package/src/langfuse/index.ts +33 -0
- package/src/langfuse/media.ts +193 -0
- package/src/langfuse/observations.ts +131 -0
- package/src/langfuse/prompts.ts +157 -0
- package/src/langfuse/scores.ts +456 -0
- package/src/langfuse/traces.ts +276 -0
- package/src/llm.ts +106 -0
- package/src/narrative/graph-manager.ts +1358 -0
- package/src/narrative/index.ts +32 -0
- package/src/narrative/markdown-export.ts +535 -0
- package/src/narrative/tool-definitions.ts +635 -0
- package/src/narrative/tool-handlers.ts +528 -0
- package/src/narrative/types.ts +9 -0
- package/src/narrative/validation.ts +179 -0
- package/src/pde/index.ts +8 -0
- package/src/pde/mcp-handlers.ts +359 -0
- package/src/pde/mcp-tools.ts +201 -0
- package/src/pde/session-manager.ts +248 -0
- package/src/pde/stc-mapper.ts +298 -0
- package/src/pipeline/index.ts +7 -0
- package/src/pipeline/template-engine.ts +398 -0
- package/src/planning/index.ts +13 -0
- package/src/planning/mcp-handlers.ts +369 -0
- package/src/planning/mcp-tools.ts +155 -0
- package/src/planning/plan-parser.ts +587 -0
- package/src/redis.ts +97 -0
- package/src/types.ts +280 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# @modelcontextprotocol/sdk: Technical Assessment for CoAiA.js
|
|
2
|
+
|
|
3
|
+
> Package selection brief — MCP server and client framework for exposing CoAiA tools, resources, and prompts to LLM agents
|
|
4
|
+
|
|
5
|
+
## Summary & Recommendation
|
|
6
|
+
|
|
7
|
+
**Use `@modelcontextprotocol/sdk` v1.x** (currently 1.27.x). This is the official Tier-1 TypeScript SDK for the Model Context Protocol. It's already used by coaia-pde, coaia-planning, and coaia-narrative. For coaiajs, we consolidate all three MCP servers into a single unified server with Zod-validated tools. Stick with v1 until v2 reaches stable (expected Q2 2026).
|
|
8
|
+
|
|
9
|
+
**Pin:** `"@modelcontextprotocol/sdk": "^1.25.0"` + `"zod": "^4.0.0"` (peer dependency)
|
|
10
|
+
|
|
11
|
+
## What We're Replacing
|
|
12
|
+
|
|
13
|
+
Three separate MCP servers each with their own Server instance:
|
|
14
|
+
|
|
15
|
+
### coaia-pde (Server + raw JSON schemas)
|
|
16
|
+
```typescript
|
|
17
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
18
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
19
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
20
|
+
|
|
21
|
+
const server = new Server(
|
|
22
|
+
{ name: 'coaia-pde', version: '1.0.0' },
|
|
23
|
+
{ capabilities: { tools: {} } }
|
|
24
|
+
);
|
|
25
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
26
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
27
|
+
const { name, arguments: args } = request.params;
|
|
28
|
+
switch(name) { case 'import_pde_decomposition': /* ... */ }
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### coaia-planning (Server + minimist config)
|
|
33
|
+
```typescript
|
|
34
|
+
const args = minimist(process.argv.slice(2));
|
|
35
|
+
const PLANS_DIR = args['plans-dir'] || process.env.COAIA_PLANS_DIR;
|
|
36
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
37
|
+
switch (name) {
|
|
38
|
+
case 'parse_plan_structural': /* ... */
|
|
39
|
+
case 'plan_to_stc': /* ... */
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### coaia-narrative (Server + custom validation.ts)
|
|
45
|
+
```typescript
|
|
46
|
+
// Uses custom validation.ts for argument checking before processing
|
|
47
|
+
const { valid, error } = validate(args, EntityArraySchema);
|
|
48
|
+
if (!valid) return errorResponse(error);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
All three use the **low-level** `Server` class with raw `setRequestHandler` and manual JSON schema definitions. The SDK's higher-level `McpServer` class with Zod eliminates this boilerplate.
|
|
52
|
+
|
|
53
|
+
## Options Compared
|
|
54
|
+
|
|
55
|
+
| Feature | McpServer (high-level) | Server (low-level) | Custom HTTP |
|
|
56
|
+
|---------|----------------------|-------------------|-------------|
|
|
57
|
+
| Tool definition | `server.tool(name, schema, handler)` | Manual `setRequestHandler` + switch | Manual routing |
|
|
58
|
+
| Schema validation | Zod automatic | Manual JSON Schema | Manual |
|
|
59
|
+
| Type inference | Full from Zod schemas | Manual casting | None |
|
|
60
|
+
| Resource support | `server.resource()` | Manual handler | Manual |
|
|
61
|
+
| Prompt templates | `server.prompt()` | Manual handler | N/A |
|
|
62
|
+
| Transport | Stdio, HTTP, SSE built-in | Stdio, HTTP, SSE built-in | Custom |
|
|
63
|
+
| Code per tool | ~10 lines | ~25 lines | ~50 lines |
|
|
64
|
+
| Used by our projects | New for coaiajs | coaia-pde, coaia-planning, coaia-narrative | N/A |
|
|
65
|
+
|
|
66
|
+
## API Overview
|
|
67
|
+
|
|
68
|
+
### Unified MCP Server (High-Level API)
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// mcp/server.ts — single unified MCP server for coaiajs
|
|
72
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
73
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
74
|
+
import { z } from 'zod';
|
|
75
|
+
|
|
76
|
+
const server = new McpServer({
|
|
77
|
+
name: 'coaiajs',
|
|
78
|
+
version: '1.0.0',
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// --- NARRATIVE TOOLS ---
|
|
82
|
+
|
|
83
|
+
server.tool(
|
|
84
|
+
'create_structural_tension_chart',
|
|
85
|
+
'Create a new structural tension chart with desired outcome and current reality',
|
|
86
|
+
{
|
|
87
|
+
desiredOutcome: z.string().min(1).describe('What you want to CREATE'),
|
|
88
|
+
currentReality: z.string().min(1).describe('Factual assessment — never "ready to begin"'),
|
|
89
|
+
dueDate: z.string().datetime().optional().describe('ISO 8601 target date'),
|
|
90
|
+
actionSteps: z.array(z.string()).optional().describe('Initial action steps'),
|
|
91
|
+
},
|
|
92
|
+
async ({ desiredOutcome, currentReality, dueDate, actionSteps }) => {
|
|
93
|
+
const chart = await createChart({ desiredOutcome, currentReality, dueDate, actionSteps });
|
|
94
|
+
return { content: [{ type: 'text', text: JSON.stringify(chart) }] };
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
server.tool(
|
|
99
|
+
'mark_action_complete',
|
|
100
|
+
'Mark an action step as completed',
|
|
101
|
+
{
|
|
102
|
+
actionStepName: z.string().min(1).describe('Name of the completed action step'),
|
|
103
|
+
},
|
|
104
|
+
async ({ actionStepName }) => {
|
|
105
|
+
const result = await markComplete(actionStepName);
|
|
106
|
+
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
// --- PDE TOOLS ---
|
|
111
|
+
|
|
112
|
+
server.tool(
|
|
113
|
+
'pde_decompose',
|
|
114
|
+
'Decompose a complex prompt into structured facets',
|
|
115
|
+
{
|
|
116
|
+
prompt: z.string().min(1).describe('The complex prompt to decompose'),
|
|
117
|
+
extractImplicit: z.boolean().default(true).describe('Extract implicit intents'),
|
|
118
|
+
mapDependencies: z.boolean().default(true).describe('Map inter-facet dependencies'),
|
|
119
|
+
},
|
|
120
|
+
async ({ prompt, extractImplicit, mapDependencies }) => {
|
|
121
|
+
const result = await decompose(prompt, { extractImplicit, mapDependencies });
|
|
122
|
+
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// --- PLANNING TOOLS ---
|
|
127
|
+
|
|
128
|
+
server.tool(
|
|
129
|
+
'parse_plan_structural',
|
|
130
|
+
'Parse a plan into structural tension format',
|
|
131
|
+
{
|
|
132
|
+
planPath: z.string().optional().describe('Path to plan file'),
|
|
133
|
+
planContent: z.string().optional().describe('Raw plan content'),
|
|
134
|
+
},
|
|
135
|
+
async ({ planPath, planContent }) => {
|
|
136
|
+
const parsed = planPath ? await parsePlan(planPath) : parsePlanContent(planContent!);
|
|
137
|
+
return { content: [{ type: 'text', text: JSON.stringify(parsed) }] };
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Resources (Read-Only Data)
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Expose chart data as MCP resources
|
|
146
|
+
server.resource(
|
|
147
|
+
'charts',
|
|
148
|
+
'chart://list',
|
|
149
|
+
async (uri) => {
|
|
150
|
+
const charts = await listActiveCharts();
|
|
151
|
+
return {
|
|
152
|
+
contents: [{
|
|
153
|
+
uri: uri.href,
|
|
154
|
+
mimeType: 'application/json',
|
|
155
|
+
text: JSON.stringify(charts),
|
|
156
|
+
}],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
// Dynamic resource with URI template
|
|
162
|
+
server.resource(
|
|
163
|
+
'chart-detail',
|
|
164
|
+
'chart://{chartId}',
|
|
165
|
+
async (uri, { chartId }) => {
|
|
166
|
+
const chart = await getChart(chartId);
|
|
167
|
+
return {
|
|
168
|
+
contents: [{
|
|
169
|
+
uri: uri.href,
|
|
170
|
+
mimeType: 'application/json',
|
|
171
|
+
text: JSON.stringify(chart),
|
|
172
|
+
}],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Prompt Templates
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
server.prompt(
|
|
182
|
+
'mmot-evaluation',
|
|
183
|
+
'MMOT self-evaluation prompt for structural tension chart',
|
|
184
|
+
{
|
|
185
|
+
chartId: z.string().describe('Chart ID to evaluate'),
|
|
186
|
+
direction: z.enum(['South', 'East', 'West', 'North']).optional(),
|
|
187
|
+
},
|
|
188
|
+
async ({ chartId, direction }) => {
|
|
189
|
+
const chart = await getChart(chartId);
|
|
190
|
+
return {
|
|
191
|
+
messages: [{
|
|
192
|
+
role: 'user',
|
|
193
|
+
content: {
|
|
194
|
+
type: 'text',
|
|
195
|
+
text: `Evaluate chart "${chart.desiredOutcome}" from ${direction ?? 'all'} direction(s)...`,
|
|
196
|
+
},
|
|
197
|
+
}],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
);
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Transport & Startup
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// Stdio transport (default for CLI agent integration)
|
|
207
|
+
async function main() {
|
|
208
|
+
const transport = new StdioServerTransport();
|
|
209
|
+
await server.connect(transport);
|
|
210
|
+
console.error('coaiajs MCP server running on stdio');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
main().catch(console.error);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Low-Level API (when needed)
|
|
217
|
+
|
|
218
|
+
For advanced scenarios (custom transports, middleware, session state), the low-level `Server` class remains available:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
222
|
+
|
|
223
|
+
const lowLevelServer = new Server(
|
|
224
|
+
{ name: 'coaiajs-advanced', version: '1.0.0' },
|
|
225
|
+
{ capabilities: { tools: {}, resources: {}, prompts: {} } }
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
// Custom request handler with full control
|
|
229
|
+
lowLevelServer.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
230
|
+
// Pre-processing middleware, custom logging, etc.
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Integration Plan
|
|
235
|
+
|
|
236
|
+
1. **Unified server:** `mcp/server.ts` — single McpServer combining all tools
|
|
237
|
+
2. **Tool modules:** `mcp/tools/` directory
|
|
238
|
+
- `narrative.ts` — chart CRUD, action steps, MMOT
|
|
239
|
+
- `pde.ts` — prompt decomposition tools
|
|
240
|
+
- `planning.ts` — plan parsing, STC conversion
|
|
241
|
+
- `pipeline.ts` — pipeline template execution
|
|
242
|
+
- `langfuse.ts` — trace/score management
|
|
243
|
+
3. **Resources:** `mcp/resources/` — chart data, session data, template listings
|
|
244
|
+
4. **Prompts:** `mcp/prompts/` — MMOT evaluation, PDE system prompts
|
|
245
|
+
5. **Bin entry:** `"coaiajs-mcp": "./dist/mcp/server.js"` in package.json
|
|
246
|
+
6. **Migration:** Gradually absorb coaia-pde, coaia-planning, coaia-narrative tools
|
|
247
|
+
|
|
248
|
+
### Tool Registration Pattern
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// mcp/tools/index.ts — register all tool modules
|
|
252
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
253
|
+
|
|
254
|
+
export function registerAllTools(server: McpServer) {
|
|
255
|
+
registerNarrativeTools(server);
|
|
256
|
+
registerPdeTools(server);
|
|
257
|
+
registerPlanningTools(server);
|
|
258
|
+
registerPipelineTools(server);
|
|
259
|
+
registerLangfuseTools(server);
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Version & Ecosystem
|
|
264
|
+
|
|
265
|
+
| Metric | Value |
|
|
266
|
+
|--------|-------|
|
|
267
|
+
| Current version | 1.27.1 (Feb 2026) |
|
|
268
|
+
| V2 status | Pre-alpha on main branch, stable Q1-Q2 2026 |
|
|
269
|
+
| Peer dependency | zod ≥3.25 |
|
|
270
|
+
| Transports | stdio, Streamable HTTP, SSE |
|
|
271
|
+
| Node.js compat | ≥18 (we target ≥20) |
|
|
272
|
+
| TypeScript | Native, first-class |
|
|
273
|
+
| Protocol spec | modelcontextprotocol.io |
|
|
274
|
+
| Weekly downloads | Growing rapidly (protocol adoption) |
|
|
275
|
+
| License | MIT |
|
|
276
|
+
|
|
277
|
+
## V1 → V2 Migration Notes
|
|
278
|
+
|
|
279
|
+
V2 (pre-alpha) brings breaking changes. Our plan:
|
|
280
|
+
- Build on V1 now (`^1.25.0`)
|
|
281
|
+
- V1 will receive security updates for 6+ months post-V2 release
|
|
282
|
+
- When V2 stabilizes, migrate — the high-level McpServer API is expected to remain similar
|
|
283
|
+
|
|
284
|
+
## References
|
|
285
|
+
|
|
286
|
+
- npm: https://www.npmjs.com/package/@modelcontextprotocol/sdk
|
|
287
|
+
- GitHub: https://github.com/modelcontextprotocol/typescript-sdk
|
|
288
|
+
- Protocol docs: https://modelcontextprotocol.io/docs/sdk
|
|
289
|
+
- API reference: https://markaicode.com/mcp-typescript-sdk-api-reference/
|
|
290
|
+
- V2 docs: https://ts.sdk.modelcontextprotocol.io/v2/
|
|
291
|
+
- Tutorial: https://dev.to/1xapi/how-to-build-mcp-servers-in-nodejs-for-ai-agents-2026-guide-fdi
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# @octokit/rest: Technical Assessment for CoAiA.js
|
|
2
|
+
|
|
3
|
+
> Package selection brief — GitHub REST API client replacing coaiapy's raw requests in cogh.py
|
|
4
|
+
|
|
5
|
+
## Summary & Recommendation
|
|
6
|
+
|
|
7
|
+
**Use `@octokit/rest` v22.x** (currently 22.0.1). Octokit is the official GitHub-maintained JavaScript client for the GitHub REST API. It replaces coaiapy's `cogh.py` which manually constructs HTTP requests with auth headers. Octokit provides typed methods for every GitHub endpoint, automatic pagination, built-in authentication, and rate limit handling.
|
|
8
|
+
|
|
9
|
+
**Pin:** `"@octokit/rest": "^22.0.0"`
|
|
10
|
+
|
|
11
|
+
## What We're Replacing
|
|
12
|
+
|
|
13
|
+
Coaiapy's `cogh.py` uses raw HTTP requests:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
# coaiapy/cogh.py — manual GitHub API
|
|
17
|
+
import requests
|
|
18
|
+
import os
|
|
19
|
+
|
|
20
|
+
def _get_github_headers():
|
|
21
|
+
config = read_config()
|
|
22
|
+
token = config.get("github", {}).get("api_token") or os.getenv("GH_TOKEN")
|
|
23
|
+
return {
|
|
24
|
+
"Authorization": f"Bearer {token}",
|
|
25
|
+
"Accept": "application/vnd.github.v3+json"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
def list_issues(owner, repo):
|
|
29
|
+
headers = _get_github_headers()
|
|
30
|
+
response = requests.get(
|
|
31
|
+
f"https://api.github.com/repos/{owner}/{repo}/issues",
|
|
32
|
+
headers=headers
|
|
33
|
+
)
|
|
34
|
+
return response.json()
|
|
35
|
+
|
|
36
|
+
def get_issue(owner, repo, issue_number):
|
|
37
|
+
headers = _get_github_headers()
|
|
38
|
+
response = requests.get(
|
|
39
|
+
f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}",
|
|
40
|
+
headers=headers
|
|
41
|
+
)
|
|
42
|
+
return response.json()
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Issues: no pagination handling, no rate limit awareness, no type safety, manual URL construction, no retry logic.
|
|
46
|
+
|
|
47
|
+
## Options Compared
|
|
48
|
+
|
|
49
|
+
| Feature | @octokit/rest v22 | Raw fetch/requests | graphql (@octokit/graphql) |
|
|
50
|
+
|---------|-------------------|-------------------|--------------------------|
|
|
51
|
+
| API coverage | All REST endpoints typed | Manual per endpoint | GraphQL (different paradigm) |
|
|
52
|
+
| Authentication | Token, App, OAuth, Action | Manual headers | Same as octokit |
|
|
53
|
+
| Pagination | `octokit.paginate()` automatic | Manual `Link` header parsing | Cursor-based (manual) |
|
|
54
|
+
| Rate limiting | Built-in retry plugin | Manual `X-RateLimit-*` handling | Same as octokit |
|
|
55
|
+
| TypeScript | Full types for every endpoint | Manual interfaces | Partial |
|
|
56
|
+
| Request/response hooks | Plugin system | Manual interceptors | Plugin system |
|
|
57
|
+
| Bundle size | ~150KB | 0 | ~50KB |
|
|
58
|
+
| Maintenance | GitHub-maintained official | N/A | GitHub-maintained official |
|
|
59
|
+
|
|
60
|
+
## API Overview
|
|
61
|
+
|
|
62
|
+
### Client Setup
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { Octokit } from '@octokit/rest';
|
|
66
|
+
import { loadConfig } from '../config.js';
|
|
67
|
+
|
|
68
|
+
const config = loadConfig();
|
|
69
|
+
|
|
70
|
+
const octokit = new Octokit({
|
|
71
|
+
auth: config.githubToken ?? process.env.GH_TOKEN,
|
|
72
|
+
userAgent: 'coaiajs/1.0.0',
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Issues API (replacing cogh.py)
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// List issues (replaces cogh.list_issues)
|
|
80
|
+
async function listIssues(owner: string, repo: string, options?: {
|
|
81
|
+
state?: 'open' | 'closed' | 'all';
|
|
82
|
+
labels?: string[];
|
|
83
|
+
per_page?: number;
|
|
84
|
+
}) {
|
|
85
|
+
const { data } = await octokit.rest.issues.listForRepo({
|
|
86
|
+
owner,
|
|
87
|
+
repo,
|
|
88
|
+
state: options?.state ?? 'open',
|
|
89
|
+
labels: options?.labels?.join(','),
|
|
90
|
+
per_page: options?.per_page ?? 30,
|
|
91
|
+
});
|
|
92
|
+
return data;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Get single issue (replaces cogh.get_issue)
|
|
96
|
+
async function getIssue(owner: string, repo: string, issueNumber: number) {
|
|
97
|
+
const { data } = await octokit.rest.issues.get({
|
|
98
|
+
owner,
|
|
99
|
+
repo,
|
|
100
|
+
issue_number: issueNumber,
|
|
101
|
+
});
|
|
102
|
+
return data;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Create issue
|
|
106
|
+
async function createIssue(owner: string, repo: string, title: string, body: string, labels?: string[]) {
|
|
107
|
+
const { data } = await octokit.rest.issues.create({
|
|
108
|
+
owner,
|
|
109
|
+
repo,
|
|
110
|
+
title,
|
|
111
|
+
body,
|
|
112
|
+
labels,
|
|
113
|
+
});
|
|
114
|
+
return data;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Add comment to issue
|
|
118
|
+
async function commentOnIssue(owner: string, repo: string, issueNumber: number, body: string) {
|
|
119
|
+
const { data } = await octokit.rest.issues.createComment({
|
|
120
|
+
owner,
|
|
121
|
+
repo,
|
|
122
|
+
issue_number: issueNumber,
|
|
123
|
+
body,
|
|
124
|
+
});
|
|
125
|
+
return data;
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Automatic Pagination
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// Fetch ALL issues across all pages
|
|
133
|
+
async function listAllIssues(owner: string, repo: string) {
|
|
134
|
+
const issues = await octokit.paginate(octokit.rest.issues.listForRepo, {
|
|
135
|
+
owner,
|
|
136
|
+
repo,
|
|
137
|
+
state: 'all',
|
|
138
|
+
per_page: 100,
|
|
139
|
+
});
|
|
140
|
+
return issues; // All pages concatenated
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Session Management (Miadi webhook pattern)
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// Create issue for agent session tracking
|
|
148
|
+
async function createSessionIssue(
|
|
149
|
+
owner: string,
|
|
150
|
+
repo: string,
|
|
151
|
+
sessionId: string,
|
|
152
|
+
metadata: Record<string, string>
|
|
153
|
+
) {
|
|
154
|
+
const body = [
|
|
155
|
+
`## Agent Session: ${sessionId}`,
|
|
156
|
+
'',
|
|
157
|
+
'| Key | Value |',
|
|
158
|
+
'|-----|-------|',
|
|
159
|
+
...Object.entries(metadata).map(([k, v]) => `| ${k} | ${v} |`),
|
|
160
|
+
].join('\n');
|
|
161
|
+
|
|
162
|
+
return createIssue(owner, repo, `Session: ${sessionId}`, body, ['agent-session']);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Update session with results
|
|
166
|
+
async function updateSessionIssue(
|
|
167
|
+
owner: string,
|
|
168
|
+
repo: string,
|
|
169
|
+
issueNumber: number,
|
|
170
|
+
results: string
|
|
171
|
+
) {
|
|
172
|
+
await commentOnIssue(owner, repo, issueNumber, results);
|
|
173
|
+
|
|
174
|
+
// Close when session completes
|
|
175
|
+
await octokit.rest.issues.update({
|
|
176
|
+
owner,
|
|
177
|
+
repo,
|
|
178
|
+
issue_number: issueNumber,
|
|
179
|
+
state: 'closed',
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Repository Operations
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
// Get file contents
|
|
188
|
+
async function getFileContent(owner: string, repo: string, path: string, ref?: string) {
|
|
189
|
+
const { data } = await octokit.rest.repos.getContent({
|
|
190
|
+
owner,
|
|
191
|
+
repo,
|
|
192
|
+
path,
|
|
193
|
+
ref,
|
|
194
|
+
});
|
|
195
|
+
if ('content' in data) {
|
|
196
|
+
return Buffer.from(data.content, 'base64').toString('utf-8');
|
|
197
|
+
}
|
|
198
|
+
throw new Error(`${path} is not a file`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// List commits
|
|
202
|
+
async function listRecentCommits(owner: string, repo: string, count = 10) {
|
|
203
|
+
const { data } = await octokit.rest.repos.listCommits({
|
|
204
|
+
owner,
|
|
205
|
+
repo,
|
|
206
|
+
per_page: count,
|
|
207
|
+
});
|
|
208
|
+
return data.map(c => ({
|
|
209
|
+
sha: c.sha.slice(0, 7),
|
|
210
|
+
message: c.commit.message.split('\n')[0],
|
|
211
|
+
author: c.commit.author?.name,
|
|
212
|
+
date: c.commit.author?.date,
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Authentication Patterns
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
// Pattern 1: Personal Access Token (default)
|
|
221
|
+
const octokit = new Octokit({ auth: process.env.GH_TOKEN });
|
|
222
|
+
|
|
223
|
+
// Pattern 2: GitHub Actions token
|
|
224
|
+
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
|
|
225
|
+
|
|
226
|
+
// Pattern 3: GitHub App (for Miadi webhook integration)
|
|
227
|
+
import { createAppAuth } from '@octokit/auth-app';
|
|
228
|
+
|
|
229
|
+
const octokit = new Octokit({
|
|
230
|
+
authStrategy: createAppAuth,
|
|
231
|
+
auth: {
|
|
232
|
+
appId: config.githubAppId,
|
|
233
|
+
privateKey: config.githubPrivateKey,
|
|
234
|
+
installationId: config.githubInstallationId,
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Formatting (replacing cogh.format_issues_table)
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
function formatIssuesTable(issues: Awaited<ReturnType<typeof listIssues>>): string {
|
|
243
|
+
const header = '| # | Title | State | Labels | Updated |';
|
|
244
|
+
const separator = '|---|-------|-------|--------|---------|';
|
|
245
|
+
const rows = issues.map(i =>
|
|
246
|
+
`| ${i.number} | ${i.title} | ${i.state} | ${i.labels.map(l =>
|
|
247
|
+
typeof l === 'string' ? l : l.name).join(', ')} | ${i.updated_at?.slice(0, 10)} |`
|
|
248
|
+
);
|
|
249
|
+
return [header, separator, ...rows].join('\n');
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Integration Plan
|
|
254
|
+
|
|
255
|
+
1. **Core client:** `src/github/client.ts` — Octokit singleton from config
|
|
256
|
+
2. **Issues module:** `src/github/issues.ts` — CRUD + pagination (replaces cogh.py)
|
|
257
|
+
3. **Session tracking:** `src/github/sessions.ts` — issue-based session management
|
|
258
|
+
4. **Repository module:** `src/github/repos.ts` — file content, commits
|
|
259
|
+
5. **CLI command:** `src/commands/gh.ts` — Commander subcommand for GitHub ops
|
|
260
|
+
6. **MCP tool:** `mcp/tools/github.ts` — GitHub operations as agent tools
|
|
261
|
+
7. **Auth:** Support PAT, Actions token, and GitHub App auth
|
|
262
|
+
|
|
263
|
+
## Version & Ecosystem
|
|
264
|
+
|
|
265
|
+
| Metric | Value |
|
|
266
|
+
|--------|-------|
|
|
267
|
+
| Current version | 22.0.1 (Feb 2026) |
|
|
268
|
+
| Weekly downloads | ~10M+ |
|
|
269
|
+
| TypeScript | Full native types for every endpoint |
|
|
270
|
+
| Node.js compat | ≥20 (v22 dropped Node 18) |
|
|
271
|
+
| Authentication | PAT, OAuth, App, Actions |
|
|
272
|
+
| Pagination | Built-in `octokit.paginate()` |
|
|
273
|
+
| Rate limiting | Plugin-based retry |
|
|
274
|
+
| Maintained by | GitHub (official) |
|
|
275
|
+
| License | MIT |
|
|
276
|
+
|
|
277
|
+
### Ecosystem Packages
|
|
278
|
+
|
|
279
|
+
| Package | Purpose | When to Use |
|
|
280
|
+
|---------|---------|-------------|
|
|
281
|
+
| `@octokit/rest` | REST API client | Primary — all REST operations |
|
|
282
|
+
| `@octokit/graphql` | GraphQL API | Complex queries (PR reviews, nested data) |
|
|
283
|
+
| `@octokit/auth-app` | GitHub App auth | Miadi webhook integration |
|
|
284
|
+
| `@octokit/webhooks` | Webhook handling | Receiving GitHub webhooks |
|
|
285
|
+
| `@octokit/plugin-paginate-rest` | Pagination | Included in @octokit/rest |
|
|
286
|
+
|
|
287
|
+
## References
|
|
288
|
+
|
|
289
|
+
- npm: https://www.npmjs.com/package/@octokit/rest
|
|
290
|
+
- GitHub: https://github.com/octokit/rest.js
|
|
291
|
+
- Docs: https://octokit.github.io/rest.js/v22/
|
|
292
|
+
- Auth patterns: https://github.com/octokit/auth-app.js
|
|
293
|
+
- Releases: https://github.com/octokit/rest.js/releases
|