@portel/photon-core 1.0.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/LICENSE +21 -0
- package/README.md +403 -0
- package/dist/base.d.ts +58 -0
- package/dist/base.d.ts.map +1 -0
- package/dist/base.js +92 -0
- package/dist/base.js.map +1 -0
- package/dist/dependency-manager.d.ts +49 -0
- package/dist/dependency-manager.d.ts.map +1 -0
- package/dist/dependency-manager.js +165 -0
- package/dist/dependency-manager.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/schema-extractor.d.ts +110 -0
- package/dist/schema-extractor.d.ts.map +1 -0
- package/dist/schema-extractor.js +727 -0
- package/dist/schema-extractor.js.map +1 -0
- package/dist/types.d.ts +109 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -0
- package/src/base.ts +105 -0
- package/src/dependency-manager.ts +206 -0
- package/src/index.ts +46 -0
- package/src/schema-extractor.ts +833 -0
- package/src/types.ts +117 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Portel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
# @portel/photon-core
|
|
2
|
+
|
|
3
|
+
**Core library for parsing, loading, and managing `.photon.ts` files**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@portel/photon-core)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## 🎯 What is Photon Core?
|
|
9
|
+
|
|
10
|
+
Photon Core is the **runtime-agnostic foundation** for working with `.photon.ts` files. It provides:
|
|
11
|
+
|
|
12
|
+
- ✅ **Base class** with lifecycle hooks (`onInitialize`, `onShutdown`)
|
|
13
|
+
- ✅ **Dependency management** - Extract and install `@dependencies` from JSDoc
|
|
14
|
+
- ✅ **Schema extraction** - Parse TypeScript types and JSDoc into JSON schemas
|
|
15
|
+
- ❌ **NO runtime layers** - No MCP server, no CLI, no transport
|
|
16
|
+
|
|
17
|
+
This allows you to build **custom runtimes** on top of the Photon format:
|
|
18
|
+
- **Multi-protocol API servers** (REST, GraphQL, RPC, MCP) → [Lumina](https://github.com/portel-dev/lumina)
|
|
19
|
+
- **Orchestrators** → [NCP](https://github.com/portel-dev/ncp)
|
|
20
|
+
- **MCP/CLI runners** → [@portel/photon](https://github.com/portel-dev/photon)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 📦 Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @portel/photon-core
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🚀 Quick Start
|
|
33
|
+
|
|
34
|
+
### 1. Create a Photon class
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
// calculator.photon.ts
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Simple calculator with basic math operations
|
|
41
|
+
* @dependencies lodash@^4.17.21
|
|
42
|
+
*/
|
|
43
|
+
export default class Calculator {
|
|
44
|
+
/**
|
|
45
|
+
* Add two numbers together
|
|
46
|
+
* @param a First number
|
|
47
|
+
* @param b Second number
|
|
48
|
+
*/
|
|
49
|
+
async add(params: { a: number; b: number }) {
|
|
50
|
+
return params.a + params.b;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Multiply two numbers
|
|
55
|
+
* @param a First number
|
|
56
|
+
* @param b Second number
|
|
57
|
+
*/
|
|
58
|
+
async multiply(params: { a: number; b: number }) {
|
|
59
|
+
return params.a * params.b;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Lifecycle hook called when photon is initialized
|
|
64
|
+
*/
|
|
65
|
+
async onInitialize() {
|
|
66
|
+
console.log('Calculator initialized!');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Lifecycle hook called when photon is shut down
|
|
71
|
+
*/
|
|
72
|
+
async onShutdown() {
|
|
73
|
+
console.log('Calculator shutting down!');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2. Use Photon Core to load and manage it
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { PhotonMCP, DependencyManager, SchemaExtractor } from '@portel/photon-core';
|
|
82
|
+
|
|
83
|
+
// 1. Extract and install dependencies
|
|
84
|
+
const depManager = new DependencyManager();
|
|
85
|
+
const deps = await depManager.extractDependencies('./calculator.photon.ts');
|
|
86
|
+
// Found: [{ name: 'lodash', version: '^4.17.21' }]
|
|
87
|
+
|
|
88
|
+
await depManager.ensureDependencies('calculator', deps);
|
|
89
|
+
// ✅ Dependencies installed
|
|
90
|
+
|
|
91
|
+
// 2. Load the class
|
|
92
|
+
const CalculatorClass = (await import('./calculator.photon.ts')).default;
|
|
93
|
+
const instance = new CalculatorClass();
|
|
94
|
+
|
|
95
|
+
// 3. Call lifecycle hook
|
|
96
|
+
if (instance.onInitialize) {
|
|
97
|
+
await instance.onInitialize();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 4. Extract schemas (optional)
|
|
101
|
+
const extractor = new SchemaExtractor();
|
|
102
|
+
const schemas = await extractor.extractFromFile('./calculator.photon.ts');
|
|
103
|
+
console.log(schemas);
|
|
104
|
+
// [
|
|
105
|
+
// {
|
|
106
|
+
// name: 'add',
|
|
107
|
+
// description: 'Add two numbers together',
|
|
108
|
+
// inputSchema: {
|
|
109
|
+
// type: 'object',
|
|
110
|
+
// properties: {
|
|
111
|
+
// a: { type: 'number', description: 'First number' },
|
|
112
|
+
// b: { type: 'number', description: 'Second number' }
|
|
113
|
+
// },
|
|
114
|
+
// required: ['a', 'b']
|
|
115
|
+
// }
|
|
116
|
+
// },
|
|
117
|
+
// ...
|
|
118
|
+
// ]
|
|
119
|
+
|
|
120
|
+
// 5. Execute methods
|
|
121
|
+
const result = await instance.add({ a: 5, b: 3 });
|
|
122
|
+
console.log(result); // 8
|
|
123
|
+
|
|
124
|
+
// 6. Cleanup
|
|
125
|
+
if (instance.onShutdown) {
|
|
126
|
+
await instance.onShutdown();
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 📚 API Reference
|
|
133
|
+
|
|
134
|
+
### `PhotonMCP`
|
|
135
|
+
|
|
136
|
+
Base class for creating Photon classes (optional - you can use plain classes too).
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { PhotonMCP } from '@portel/photon-core';
|
|
140
|
+
|
|
141
|
+
export default class MyPhoton extends PhotonMCP {
|
|
142
|
+
async myMethod(params: { input: string }) {
|
|
143
|
+
return `Hello ${params.input}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async onInitialize() {
|
|
147
|
+
// Called when photon is loaded
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async onShutdown() {
|
|
151
|
+
// Called when photon is unloaded
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Static methods:**
|
|
157
|
+
- `getMCPName()` - Convert class name to kebab-case (e.g., `MyAwesomeMCP` → `my-awesome-mcp`)
|
|
158
|
+
- `getToolMethods()` - Get all public async methods (excludes lifecycle hooks and private methods)
|
|
159
|
+
|
|
160
|
+
**Instance methods:**
|
|
161
|
+
- `executeTool(name, params)` - Execute a method by name
|
|
162
|
+
|
|
163
|
+
**Lifecycle hooks:**
|
|
164
|
+
- `onInitialize()` - Called when photon is initialized
|
|
165
|
+
- `onShutdown()` - Called when photon is shut down
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### `DependencyManager`
|
|
170
|
+
|
|
171
|
+
Extracts and installs npm dependencies declared in JSDoc `@dependencies` tags.
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { DependencyManager } from '@portel/photon-core';
|
|
175
|
+
|
|
176
|
+
const depManager = new DependencyManager();
|
|
177
|
+
|
|
178
|
+
// Extract dependencies from source file
|
|
179
|
+
const deps = await depManager.extractDependencies('./my-tool.photon.ts');
|
|
180
|
+
// [{ name: 'axios', version: '^1.0.0' }, { name: 'date-fns', version: '^2.0.0' }]
|
|
181
|
+
|
|
182
|
+
// Install dependencies to isolated cache
|
|
183
|
+
await depManager.ensureDependencies('my-tool', deps);
|
|
184
|
+
// Creates ~/.cache/photon-mcp/dependencies/my-tool/node_modules/
|
|
185
|
+
|
|
186
|
+
// Clear cache for a specific photon
|
|
187
|
+
await depManager.clearCache('my-tool');
|
|
188
|
+
|
|
189
|
+
// Clear all caches
|
|
190
|
+
await depManager.clearAllCache();
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Supported JSDoc format:**
|
|
194
|
+
```typescript
|
|
195
|
+
/**
|
|
196
|
+
* @dependencies axios@^1.0.0, date-fns@^2.0.0
|
|
197
|
+
* @dependencies @octokit/rest@^19.0.0
|
|
198
|
+
*/
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
### `SchemaExtractor`
|
|
204
|
+
|
|
205
|
+
Extracts JSON schemas from TypeScript method signatures and JSDoc comments.
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import { SchemaExtractor } from '@portel/photon-core';
|
|
209
|
+
|
|
210
|
+
const extractor = new SchemaExtractor();
|
|
211
|
+
|
|
212
|
+
// Extract from file
|
|
213
|
+
const schemas = await extractor.extractFromFile('./my-tool.photon.ts');
|
|
214
|
+
|
|
215
|
+
// Extract from source string
|
|
216
|
+
const source = await fs.readFile('./my-tool.photon.ts', 'utf-8');
|
|
217
|
+
const schemas = extractor.extractFromSource(source);
|
|
218
|
+
|
|
219
|
+
// Extract constructor parameters
|
|
220
|
+
const constructorParams = extractor.extractConstructorParams(source);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Schema format:**
|
|
224
|
+
```typescript
|
|
225
|
+
interface ExtractedSchema {
|
|
226
|
+
name: string;
|
|
227
|
+
description: string;
|
|
228
|
+
inputSchema: {
|
|
229
|
+
type: 'object';
|
|
230
|
+
properties: Record<string, any>;
|
|
231
|
+
required?: string[];
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Supported JSDoc constraints:**
|
|
237
|
+
```typescript
|
|
238
|
+
/**
|
|
239
|
+
* @param age User age {@min 0} {@max 120}
|
|
240
|
+
* @param email Email address {@format email}
|
|
241
|
+
* @param username Username {@pattern ^[a-z0-9_]+$}
|
|
242
|
+
* @param count Count {@default 10}
|
|
243
|
+
*/
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 🏗️ Building Custom Runtimes
|
|
249
|
+
|
|
250
|
+
Photon Core is designed to be the foundation for custom runtimes. Here are examples:
|
|
251
|
+
|
|
252
|
+
### Example 1: REST API Server
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import express from 'express';
|
|
256
|
+
import { PhotonMCP, DependencyManager, SchemaExtractor } from '@portel/photon-core';
|
|
257
|
+
|
|
258
|
+
class PhotonRESTServer {
|
|
259
|
+
async serve(photonPath: string) {
|
|
260
|
+
const app = express();
|
|
261
|
+
|
|
262
|
+
// Load photon
|
|
263
|
+
const PhotonClass = (await import(photonPath)).default;
|
|
264
|
+
const instance = new PhotonClass();
|
|
265
|
+
await instance.onInitialize?.();
|
|
266
|
+
|
|
267
|
+
// Extract schemas
|
|
268
|
+
const extractor = new SchemaExtractor();
|
|
269
|
+
const schemas = await extractor.extractFromFile(photonPath);
|
|
270
|
+
|
|
271
|
+
// Create REST endpoints
|
|
272
|
+
schemas.forEach(schema => {
|
|
273
|
+
app.post(`/api/${schema.name}`, async (req, res) => {
|
|
274
|
+
try {
|
|
275
|
+
const result = await instance[schema.name](req.body);
|
|
276
|
+
res.json({ result });
|
|
277
|
+
} catch (error) {
|
|
278
|
+
res.status(500).json({ error: error.message });
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
app.listen(3000);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Example 2: GraphQL Server
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { buildSchema } from 'graphql';
|
|
292
|
+
import { PhotonMCP, SchemaExtractor } from '@portel/photon-core';
|
|
293
|
+
|
|
294
|
+
class PhotonGraphQLServer {
|
|
295
|
+
async generateSchema(photonPath: string) {
|
|
296
|
+
const extractor = new SchemaExtractor();
|
|
297
|
+
const schemas = await extractor.extractFromFile(photonPath);
|
|
298
|
+
|
|
299
|
+
const mutations = schemas.map(s =>
|
|
300
|
+
`${s.name}(${this.paramsToGraphQL(s.inputSchema)}): JSON`
|
|
301
|
+
).join('\n');
|
|
302
|
+
|
|
303
|
+
return buildSchema(`
|
|
304
|
+
type Mutation {
|
|
305
|
+
${mutations}
|
|
306
|
+
}
|
|
307
|
+
`);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Example 3: MCP Orchestrator
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { PhotonMCP, DependencyManager } from '@portel/photon-core';
|
|
316
|
+
|
|
317
|
+
class PhotonOrchestrator {
|
|
318
|
+
private photons = new Map();
|
|
319
|
+
|
|
320
|
+
async loadPhoton(path: string) {
|
|
321
|
+
// Install dependencies
|
|
322
|
+
const depManager = new DependencyManager();
|
|
323
|
+
const deps = await depManager.extractDependencies(path);
|
|
324
|
+
const name = basename(path, '.photon.ts');
|
|
325
|
+
await depManager.ensureDependencies(name, deps);
|
|
326
|
+
|
|
327
|
+
// Load class
|
|
328
|
+
const PhotonClass = (await import(path)).default;
|
|
329
|
+
const instance = new PhotonClass();
|
|
330
|
+
await instance.onInitialize?.();
|
|
331
|
+
|
|
332
|
+
this.photons.set(name, instance);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
async execute(photonName: string, method: string, params: any) {
|
|
336
|
+
const photon = this.photons.get(photonName);
|
|
337
|
+
return await photon[method](params);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## 🎯 Use Cases
|
|
345
|
+
|
|
346
|
+
| Project | Description | Runtime Layer |
|
|
347
|
+
|---------|-------------|---------------|
|
|
348
|
+
| **[@portel/photon](https://github.com/portel-dev/photon)** | CLI tool for running Photons as MCP servers or CLI tools | MCP server (stdio), CLI runner |
|
|
349
|
+
| **[NCP](https://github.com/portel-dev/ncp)** | Multi-MCP orchestrator with discovery and semantic search | Orchestrator, unified MCP interface |
|
|
350
|
+
| **[Lumina](https://github.com/portel-dev/lumina)** | Multi-protocol API server | REST, GraphQL, RPC, HTTP streaming MCP |
|
|
351
|
+
|
|
352
|
+
All three projects use `@portel/photon-core` for the shared format, but each adds its own runtime layer.
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## 🔧 Development
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
# Clone the repository
|
|
360
|
+
git clone https://github.com/portel-dev/photon-core.git
|
|
361
|
+
cd photon-core
|
|
362
|
+
|
|
363
|
+
# Install dependencies
|
|
364
|
+
npm install
|
|
365
|
+
|
|
366
|
+
# Build
|
|
367
|
+
npm run build
|
|
368
|
+
|
|
369
|
+
# Test
|
|
370
|
+
npm test
|
|
371
|
+
|
|
372
|
+
# Lint
|
|
373
|
+
npm run lint
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## 📄 License
|
|
379
|
+
|
|
380
|
+
MIT © [Portel](https://github.com/portel-dev)
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## 🤝 Contributing
|
|
385
|
+
|
|
386
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## 🔗 Related Projects
|
|
391
|
+
|
|
392
|
+
- **[@portel/photon](https://github.com/portel-dev/photon)** - CLI tool for running Photons
|
|
393
|
+
- **[NCP](https://github.com/portel-dev/ncp)** - Multi-MCP orchestrator
|
|
394
|
+
- **[Lumina](https://github.com/portel-dev/lumina)** - Multi-protocol API server
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## 📖 Documentation
|
|
399
|
+
|
|
400
|
+
For more information about the Photon format and ecosystem:
|
|
401
|
+
- [Photon Documentation](https://github.com/portel-dev/photon)
|
|
402
|
+
- [NCP Documentation](https://github.com/portel-dev/ncp)
|
|
403
|
+
- [Lumina Documentation](https://github.com/portel-dev/lumina)
|
package/dist/base.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PhotonMCP Base Class
|
|
3
|
+
*
|
|
4
|
+
* Optional base class for creating Photon MCPs.
|
|
5
|
+
* You don't need to extend this - any class with async methods works!
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* export default class Calculator extends PhotonMCP {
|
|
10
|
+
* /**
|
|
11
|
+
* * Add two numbers together
|
|
12
|
+
* * @param a First number
|
|
13
|
+
* * @param b Second number
|
|
14
|
+
* *\/
|
|
15
|
+
* async add(params: { a: number; b: number }) {
|
|
16
|
+
* return params.a + params.b;
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Or without extending (plain class):
|
|
22
|
+
* ```typescript
|
|
23
|
+
* export default class Calculator {
|
|
24
|
+
* async add(params: { a: number; b: number }) {
|
|
25
|
+
* return params.a + params.b;
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Simple base class for creating Photon MCPs
|
|
32
|
+
*
|
|
33
|
+
* - Class name = MCP name
|
|
34
|
+
* - Public async methods = Tools
|
|
35
|
+
* - Return value = Tool result
|
|
36
|
+
*/
|
|
37
|
+
export declare class PhotonMCP {
|
|
38
|
+
/**
|
|
39
|
+
* Get MCP name from class name
|
|
40
|
+
* Converts PascalCase to kebab-case (e.g., MyAwesomeMCP → my-awesome-mcp)
|
|
41
|
+
*/
|
|
42
|
+
static getMCPName(): string;
|
|
43
|
+
/**
|
|
44
|
+
* Get all tool methods from this class
|
|
45
|
+
* Returns all public async methods except lifecycle hooks
|
|
46
|
+
*/
|
|
47
|
+
static getToolMethods(): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Execute a tool method
|
|
50
|
+
*/
|
|
51
|
+
executeTool(toolName: string, parameters: any): Promise<any>;
|
|
52
|
+
/**
|
|
53
|
+
* Optional lifecycle hooks
|
|
54
|
+
*/
|
|
55
|
+
onInitialize?(): Promise<void>;
|
|
56
|
+
onShutdown?(): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;;;;;;GAMG;AACH,qBAAa,SAAS;IACpB;;;OAGG;IACH,MAAM,CAAC,UAAU,IAAI,MAAM;IAQ3B;;;OAGG;IACH,MAAM,CAAC,cAAc,IAAI,MAAM,EAAE;IA0BjC;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAgBlE;;OAEG;IACG,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;IAC9B,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CACnC"}
|
package/dist/base.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PhotonMCP Base Class
|
|
3
|
+
*
|
|
4
|
+
* Optional base class for creating Photon MCPs.
|
|
5
|
+
* You don't need to extend this - any class with async methods works!
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* export default class Calculator extends PhotonMCP {
|
|
10
|
+
* /**
|
|
11
|
+
* * Add two numbers together
|
|
12
|
+
* * @param a First number
|
|
13
|
+
* * @param b Second number
|
|
14
|
+
* *\/
|
|
15
|
+
* async add(params: { a: number; b: number }) {
|
|
16
|
+
* return params.a + params.b;
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Or without extending (plain class):
|
|
22
|
+
* ```typescript
|
|
23
|
+
* export default class Calculator {
|
|
24
|
+
* async add(params: { a: number; b: number }) {
|
|
25
|
+
* return params.a + params.b;
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Simple base class for creating Photon MCPs
|
|
32
|
+
*
|
|
33
|
+
* - Class name = MCP name
|
|
34
|
+
* - Public async methods = Tools
|
|
35
|
+
* - Return value = Tool result
|
|
36
|
+
*/
|
|
37
|
+
export class PhotonMCP {
|
|
38
|
+
/**
|
|
39
|
+
* Get MCP name from class name
|
|
40
|
+
* Converts PascalCase to kebab-case (e.g., MyAwesomeMCP → my-awesome-mcp)
|
|
41
|
+
*/
|
|
42
|
+
static getMCPName() {
|
|
43
|
+
return this.name
|
|
44
|
+
.replace(/MCP$/, '') // Remove "MCP" suffix if present
|
|
45
|
+
.replace(/([A-Z])/g, '-$1')
|
|
46
|
+
.toLowerCase()
|
|
47
|
+
.replace(/^-/, ''); // Remove leading dash
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get all tool methods from this class
|
|
51
|
+
* Returns all public async methods except lifecycle hooks
|
|
52
|
+
*/
|
|
53
|
+
static getToolMethods() {
|
|
54
|
+
const prototype = this.prototype;
|
|
55
|
+
const methods = [];
|
|
56
|
+
// Get all property names from prototype chain
|
|
57
|
+
let current = prototype;
|
|
58
|
+
while (current && current !== PhotonMCP.prototype) {
|
|
59
|
+
Object.getOwnPropertyNames(current).forEach((name) => {
|
|
60
|
+
// Skip constructor, private methods (starting with _), and lifecycle hooks
|
|
61
|
+
if (name !== 'constructor' &&
|
|
62
|
+
!name.startsWith('_') &&
|
|
63
|
+
name !== 'onInitialize' &&
|
|
64
|
+
name !== 'onShutdown' &&
|
|
65
|
+
typeof prototype[name] === 'function' &&
|
|
66
|
+
!methods.includes(name)) {
|
|
67
|
+
methods.push(name);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
current = Object.getPrototypeOf(current);
|
|
71
|
+
}
|
|
72
|
+
return methods;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Execute a tool method
|
|
76
|
+
*/
|
|
77
|
+
async executeTool(toolName, parameters) {
|
|
78
|
+
const method = this[toolName];
|
|
79
|
+
if (!method || typeof method !== 'function') {
|
|
80
|
+
throw new Error(`Tool not found: ${toolName}`);
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const result = await method.call(this, parameters);
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
console.error(`Tool execution failed: ${toolName} - ${error.message}`);
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=base.js.map
|
package/dist/base.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;;;;;;GAMG;AACH,MAAM,OAAO,SAAS;IACpB;;;OAGG;IACH,MAAM,CAAC,UAAU;QACf,OAAO,IAAI,CAAC,IAAI;aACb,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,iCAAiC;aACrD,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;aAC1B,WAAW,EAAE;aACb,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,sBAAsB;IAC9C,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,cAAc;QACnB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QACjC,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,8CAA8C;QAC9C,IAAI,OAAO,GAAG,SAAS,CAAC;QACxB,OAAO,OAAO,IAAI,OAAO,KAAK,SAAS,CAAC,SAAS,EAAE,CAAC;YAClD,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBACnD,2EAA2E;gBAC3E,IACE,IAAI,KAAK,aAAa;oBACtB,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;oBACrB,IAAI,KAAK,cAAc;oBACvB,IAAI,KAAK,YAAY;oBACrB,OAAQ,SAAiB,CAAC,IAAI,CAAC,KAAK,UAAU;oBAC9C,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EACvB,CAAC;oBACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC,CAAC,CAAC;YACH,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC3C,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,QAAgB,EAAE,UAAe;QACjD,MAAM,MAAM,GAAI,IAAY,CAAC,QAAQ,CAAC,CAAC;QAEvC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACnD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,0BAA0B,QAAQ,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACvE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CAOF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Manager for Photon MCPs
|
|
3
|
+
*
|
|
4
|
+
* Handles automatic installation of dependencies declared in MCP files
|
|
5
|
+
* Similar to Python's UV or npx behavior
|
|
6
|
+
*/
|
|
7
|
+
interface DependencySpec {
|
|
8
|
+
name: string;
|
|
9
|
+
version: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Manages dependencies for Photon MCPs
|
|
13
|
+
*/
|
|
14
|
+
export declare class DependencyManager {
|
|
15
|
+
private cacheDir;
|
|
16
|
+
constructor();
|
|
17
|
+
/**
|
|
18
|
+
* Extract dependencies from MCP source file
|
|
19
|
+
*
|
|
20
|
+
* Looks for @dependencies JSDoc tag:
|
|
21
|
+
* @dependencies axios@^1.0.0, date-fns@^2.0.0
|
|
22
|
+
* @dependencies octokit@^3.1.0
|
|
23
|
+
*/
|
|
24
|
+
extractDependencies(sourceFilePath: string): Promise<DependencySpec[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Ensure dependencies are installed for an MCP
|
|
27
|
+
*
|
|
28
|
+
* Returns the path to node_modules where dependencies are installed
|
|
29
|
+
*/
|
|
30
|
+
ensureDependencies(mcpName: string, dependencies: DependencySpec[]): Promise<string | null>;
|
|
31
|
+
/**
|
|
32
|
+
* Check if dependencies are already installed
|
|
33
|
+
*/
|
|
34
|
+
private checkInstalled;
|
|
35
|
+
/**
|
|
36
|
+
* Run npm install in a directory
|
|
37
|
+
*/
|
|
38
|
+
private runNpmInstall;
|
|
39
|
+
/**
|
|
40
|
+
* Clear cache for an MCP
|
|
41
|
+
*/
|
|
42
|
+
clearCache(mcpName: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Clear all cached dependencies
|
|
45
|
+
*/
|
|
46
|
+
clearAllCache(): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=dependency-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependency-manager.d.ts","sourceRoot":"","sources":["../src/dependency-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAS;;IAOzB;;;;;;OAMG;IACG,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA0C5E;;;;OAIG;IACG,kBAAkB,CACtB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,cAAc,EAAE,GAC7B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA0CzB;;OAEG;YACW,cAAc;IA2B5B;;OAEG;YACW,aAAa;IAqB3B;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhD;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAQrC"}
|