@breadstone/archipel-mcp 0.0.10 → 0.0.11

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.
Files changed (56) hide show
  1. package/data/guides/ai-text-generation.md +361 -0
  2. package/data/guides/analytics-and-error-tracking.md +189 -0
  3. package/data/guides/authentication-and-authorization.md +657 -0
  4. package/data/guides/blob-storage.md +242 -0
  5. package/data/guides/caching.md +255 -0
  6. package/data/guides/cryptography-and-otp.md +240 -0
  7. package/data/guides/document-generation.md +174 -0
  8. package/data/guides/email-delivery.md +196 -0
  9. package/data/guides/esigning-integration.md +231 -0
  10. package/data/guides/getting-started.md +351 -0
  11. package/data/guides/implementing-ports.md +317 -0
  12. package/data/guides/index.md +61 -0
  13. package/data/guides/mcp-server.md +222 -0
  14. package/data/guides/openapi-and-feature-discovery.md +266 -0
  15. package/data/guides/payments-and-feature-gating.md +244 -0
  16. package/data/guides/resource-management.md +352 -0
  17. package/data/guides/telemetry-and-observability.md +190 -0
  18. package/data/guides/testing.md +319 -0
  19. package/data/guides/tsdoc-guidelines.md +45 -0
  20. package/data/packages/platform-openapi/api/Class.SwaggerFeatureDiscovery.md +10 -6
  21. package/package.json +1 -1
  22. package/src/GuidesLoader.d.ts +13 -0
  23. package/src/GuidesLoader.js +81 -0
  24. package/src/main.js +36 -198
  25. package/src/models/IGuideDoc.d.ts +15 -0
  26. package/src/models/IGuideDoc.js +3 -0
  27. package/src/tools/registerGetConfigPatternTool.d.ts +5 -0
  28. package/src/tools/registerGetConfigPatternTool.js +15 -0
  29. package/src/tools/registerGetDtoPatternTool.d.ts +5 -0
  30. package/src/tools/registerGetDtoPatternTool.js +15 -0
  31. package/src/tools/registerGetErrorHandlingPatternTool.d.ts +5 -0
  32. package/src/tools/registerGetErrorHandlingPatternTool.js +15 -0
  33. package/src/tools/registerGetGuardPatternTool.d.ts +5 -0
  34. package/src/tools/registerGetGuardPatternTool.js +15 -0
  35. package/src/tools/registerGetGuideTool.d.ts +6 -0
  36. package/src/tools/registerGetGuideTool.js +32 -0
  37. package/src/tools/registerGetMappingPatternTool.d.ts +5 -0
  38. package/src/tools/registerGetMappingPatternTool.js +34 -0
  39. package/src/tools/registerGetModulePatternTool.d.ts +5 -0
  40. package/src/tools/registerGetModulePatternTool.js +29 -0
  41. package/src/tools/registerGetPackageDocTool.d.ts +6 -0
  42. package/src/tools/registerGetPackageDocTool.js +43 -0
  43. package/src/tools/registerGetQueryPatternTool.d.ts +5 -0
  44. package/src/tools/registerGetQueryPatternTool.js +29 -0
  45. package/src/tools/registerGetRepositoryPatternTool.d.ts +5 -0
  46. package/src/tools/registerGetRepositoryPatternTool.js +29 -0
  47. package/src/tools/registerGetTestingPatternTool.d.ts +5 -0
  48. package/src/tools/registerGetTestingPatternTool.js +15 -0
  49. package/src/tools/registerListGuidesTool.d.ts +6 -0
  50. package/src/tools/registerListGuidesTool.js +22 -0
  51. package/src/tools/registerListPackagesTool.d.ts +6 -0
  52. package/src/tools/registerListPackagesTool.js +20 -0
  53. package/src/tools/registerSearchDocsTool.d.ts +6 -0
  54. package/src/tools/registerSearchDocsTool.js +35 -0
  55. package/src/tools/registerSearchGuidesTool.d.ts +6 -0
  56. package/src/tools/registerSearchGuidesTool.js +28 -0
@@ -0,0 +1,317 @@
1
+ ---
2
+ title: Implementing Ports
3
+ description: How the port/adapter pattern works in Archipel and how to implement adapters for each package.
4
+ order: 2
5
+ ---
6
+
7
+ # Implementing Ports
8
+
9
+ Archipel libraries don't hardcode how you store data, send emails, or check permissions. Instead, they define **ports** — abstract classes describing what the library needs — and your application provides **adapters** — concrete classes that implement those methods with your specific database, API, or logic.
10
+
11
+ This guide covers why ports are abstract classes, which ports exist across all packages, how to write and register adapters, and what happens when optional ports are omitted.
12
+
13
+ ## Why Abstract Classes?
14
+
15
+ NestJS uses a token-based dependency injection system. Every injectable needs a token for resolution. Archipel uses abstract classes as ports because they serve two purposes simultaneously:
16
+
17
+ 1. **Type contract** — They define the method signatures your adapter must implement. TypeScript enforces this at compile time.
18
+ 2. **DI token** — NestJS can use the class reference directly as an injection token, so there's no need for separate `Symbol()` tokens or string identifiers.
19
+
20
+ ```typescript
21
+ // Inside the platform library — you don't write this, it's already there
22
+ @Injectable()
23
+ export class SessionService {
24
+ constructor(
25
+ private readonly _sessionPersistence: SessionPersistencePort,
26
+ // The abstract class IS the DI token
27
+ ) {}
28
+ }
29
+ ```
30
+
31
+ When you pass `{ sessionPersistence: PrismaSessionAdapter }` to `register()`, the library binds your concrete class to the abstract class token. NestJS resolves it automatically wherever the port is injected.
32
+
33
+ ---
34
+
35
+ ## All Ports Reference
36
+
37
+ Every port across all Archipel packages:
38
+
39
+ | Package | Port | Purpose | Required |
40
+ | ------------------------- | ---------------------------- | ---------------------------------------------- | -------- |
41
+ | `platform-authentication` | `AuthSubjectPort` | User lookup for authentication strategies | Yes |
42
+ | `platform-authentication` | `MfaSubjectPort` | MFA state persistence (enable/disable, verify) | Yes |
43
+ | `platform-authentication` | `SessionPersistencePort` | Session storage, querying, and cleanup | Yes |
44
+ | `platform-authentication` | `VerificationSubjectPort` | Email/PIN verification persistence | Yes |
45
+ | `platform-authentication` | `SocialAuthPort` | OAuth user creation and account linking | No |
46
+ | `platform-authentication` | `TokenEnricherPort` | Add custom claims to JWTs | No |
47
+ | `platform-blob-storage` | `BlobObjectPersistencePort` | Track blob metadata after upload/delete | No |
48
+ | `platform-blob-storage` | `BlobVariantPersistencePort` | Track image variant metadata | No |
49
+ | `platform-payments` | `FeatureAccessPort` | Feature quota checks and usage recording | No |
50
+
51
+ Packages not listed here (`platform-core`, `platform-database`, `platform-logging`, `platform-telemetry`, `platform-openapi`, `platform-reporting`, `platform-documents`, `platform-mailing`, `platform-mcp`) have no ports — they work out of the box with configuration only.
52
+
53
+ ---
54
+
55
+ ## Writing an Adapter
56
+
57
+ ### Step 1: Create the Adapter File
58
+
59
+ Create one file per adapter in an `adapters/` directory in your application:
60
+
61
+ ```
62
+ src/
63
+ adapters/
64
+ PrismaAuthSubjectAdapter.ts
65
+ PrismaMfaSubjectAdapter.ts
66
+ PrismaSessionAdapter.ts
67
+ PrismaVerificationAdapter.ts
68
+ ```
69
+
70
+ ### Step 2: Extend the Port
71
+
72
+ ```typescript
73
+ import { Injectable } from '@nestjs/common';
74
+ import { AuthSubjectPort, type IAuthSubject } from '@breadstone/archipel-platform-authentication';
75
+ import { PrismaService } from '@breadstone/archipel-platform-database';
76
+
77
+ @Injectable()
78
+ export class PrismaAuthSubjectAdapter extends AuthSubjectPort {
79
+ private readonly _prisma: PrismaService;
80
+
81
+ constructor(prisma: PrismaService) {
82
+ super();
83
+ this._prisma = prisma;
84
+ }
85
+
86
+ public async findById(id: string): Promise<IAuthSubject | null> {
87
+ const user = await this._prisma.user.findUnique({
88
+ where: { id },
89
+ select: {
90
+ id: true,
91
+ userName: true,
92
+ email: true,
93
+ password: true,
94
+ isVerified: true,
95
+ isAnonymous: true,
96
+ roles: true,
97
+ mfaEnabled: true,
98
+ },
99
+ });
100
+
101
+ return user ?? null;
102
+ }
103
+
104
+ public async findByLogin(login: string): Promise<IAuthSubject | null> {
105
+ const user = await this._prisma.user.findFirst({
106
+ where: { OR: [{ userName: login }, { email: login }] },
107
+ select: {
108
+ id: true,
109
+ userName: true,
110
+ email: true,
111
+ password: true,
112
+ isVerified: true,
113
+ isAnonymous: true,
114
+ roles: true,
115
+ mfaEnabled: true,
116
+ },
117
+ });
118
+
119
+ return user ?? null;
120
+ }
121
+
122
+ public async findAnonymous(userName: string): Promise<IAuthSubject | null> {
123
+ const user = await this._prisma.user.findFirst({
124
+ where: { userName, isAnonymous: true },
125
+ select: {
126
+ id: true,
127
+ userName: true,
128
+ email: true,
129
+ password: true,
130
+ isVerified: true,
131
+ isAnonymous: true,
132
+ roles: true,
133
+ mfaEnabled: true,
134
+ },
135
+ });
136
+
137
+ return user ?? null;
138
+ }
139
+ }
140
+ ```
141
+
142
+ **Key rules:**
143
+
144
+ - Always annotate with `@Injectable()` — the adapter is a NestJS provider and participates in DI.
145
+ - Always call `super()` in the constructor — the abstract class may have a constructor that sets up internal state.
146
+ - Return the port's interface type (`IAuthSubject`, `ISessionRecord`, etc.), not your raw Prisma model. The port defines the contract.
147
+ - Inject your own dependencies via constructor — the adapter has full access to NestJS DI, so it can use your `PrismaService`, `HttpService`, or anything else.
148
+ - One adapter per port — don't combine multiple ports in one class. NestJS resolves each port token independently.
149
+
150
+ ### Step 3: Register
151
+
152
+ Pass the adapter class (not an instance) to the module's `register()` method:
153
+
154
+ ```typescript
155
+ AuthModule.register({
156
+ authSubject: PrismaAuthSubjectAdapter,
157
+ mfaSubject: PrismaMfaSubjectAdapter,
158
+ sessionPersistence: PrismaSessionAdapter,
159
+ verificationSubject: PrismaVerificationAdapter,
160
+ });
161
+ ```
162
+
163
+ NestJS handles instantiation and dependency resolution. You pass the class reference, the framework does the rest.
164
+
165
+ ---
166
+
167
+ ## Schema Mapping
168
+
169
+ Your database schema won't always match the port interface field-for-field. The adapter is where you handle the translation. This is one of the main reasons adapters exist — they decouple the library's expectations from your specific data model.
170
+
171
+ ```typescript
172
+ public async findById(id: string): Promise<IAuthSubject | null> {
173
+ const user = await this._prisma.user.findUnique({
174
+ where: { id },
175
+ include: { userRoles: { include: { role: true } } },
176
+ });
177
+
178
+ if (!user) return null;
179
+
180
+ return {
181
+ id: user.id,
182
+ userName: user.username, // different casing
183
+ email: user.emailAddress, // different field name
184
+ password: user.passwordHash, // different field name
185
+ isVerified: user.emailVerified, // different field name
186
+ isAnonymous: user.type === 'anonymous', // derived from enum
187
+ roles: user.userRoles.map((ur) => ur.role.name), // flattened relation
188
+ mfaEnabled: user.twoFactorEnabled, // different field name
189
+ };
190
+ }
191
+ ```
192
+
193
+ As long as the returned object satisfies the port's interface, the platform library doesn't care what your underlying schema looks like.
194
+
195
+ ---
196
+
197
+ ## Adapters for External APIs
198
+
199
+ Ports aren't limited to database adapters. You can implement an adapter that calls an external API, talks to a microservice, or reads from a cache — anything that fulfills the contract.
200
+
201
+ ```typescript
202
+ @Injectable()
203
+ export class Auth0AuthSubjectAdapter extends AuthSubjectPort {
204
+ private readonly _http: HttpService;
205
+
206
+ constructor(http: HttpService) {
207
+ super();
208
+ this._http = http;
209
+ }
210
+
211
+ public async findById(id: string): Promise<IAuthSubject | null> {
212
+ const { data } = await firstValueFrom(this._http.get(`https://my-tenant.auth0.com/api/v2/users/${id}`));
213
+
214
+ return {
215
+ id: data.user_id,
216
+ userName: data.nickname,
217
+ email: data.email,
218
+ password: '',
219
+ isVerified: data.email_verified,
220
+ isAnonymous: false,
221
+ roles: data.app_metadata?.roles ?? [],
222
+ mfaEnabled: data.multifactor?.length > 0,
223
+ };
224
+ }
225
+
226
+ public async findByLogin(login: string): Promise<IAuthSubject | null> {
227
+ const { data } = await firstValueFrom(
228
+ this._http.get('https://my-tenant.auth0.com/api/v2/users', {
229
+ params: { q: `email:"${login}" OR nickname:"${login}"` },
230
+ }),
231
+ );
232
+
233
+ return data[0] ? this.mapToAuthSubject(data[0]) : null;
234
+ }
235
+
236
+ // ...
237
+ }
238
+ ```
239
+
240
+ The library has no idea it's talking to Auth0. It calls `findById()` and gets back an `IAuthSubject` — that's the entire contract.
241
+
242
+ ---
243
+
244
+ ## In-Memory Adapters for Testing
245
+
246
+ For integration tests where you need a working port without a real database, create in-memory implementations:
247
+
248
+ ```typescript
249
+ @Injectable()
250
+ export class InMemoryAuthSubjectAdapter extends AuthSubjectPort {
251
+ private readonly _subjects = new Map<string, IAuthSubject>();
252
+
253
+ public seed(subjects: IAuthSubject[]): void {
254
+ subjects.forEach((s) => this._subjects.set(s.id, s));
255
+ }
256
+
257
+ public async findById(id: string): Promise<IAuthSubject | null> {
258
+ return this._subjects.get(id) ?? null;
259
+ }
260
+
261
+ public async findByLogin(login: string): Promise<IAuthSubject | null> {
262
+ return [...this._subjects.values()].find((s) => s.userName === login || s.email === login) ?? null;
263
+ }
264
+
265
+ public async findAnonymous(userName: string): Promise<IAuthSubject | null> {
266
+ return [...this._subjects.values()].find((s) => s.userName === userName && s.isAnonymous) ?? null;
267
+ }
268
+ }
269
+ ```
270
+
271
+ This pattern works for any port. Seed with test data, inject into the module under test, and your tests run fast and deterministically without database fixtures. See the [Testing](/guides/testing) guide for full integration test examples.
272
+
273
+ ---
274
+
275
+ ## Optional Ports
276
+
277
+ Some ports are optional. When not provided, the library gracefully degrades — the feature that depends on that port simply isn't available. The library's internal services use `@Optional()` on the injection, so they receive `undefined` and skip the corresponding logic.
278
+
279
+ ### TokenEnricherPort (Authentication)
280
+
281
+ When omitted, JWTs contain only the base claims (`id`, `email`, `roles`). When provided, `AuthTokenService` calls your adapter's `enrichClaims()` method and merges the result into every token.
282
+
283
+ ```typescript
284
+ @Injectable()
285
+ export class AppTokenEnricherAdapter extends TokenEnricherPort {
286
+ public async enrichClaims(subject: IAuthSubject): Promise<Record<string, unknown>> {
287
+ return {
288
+ subscriptionTier: 'pro',
289
+ organizationId: 'org-123',
290
+ };
291
+ }
292
+ }
293
+ ```
294
+
295
+ ### SocialAuthPort (Authentication)
296
+
297
+ When omitted, OAuth strategies (GitHub, Google, Microsoft, Apple) are not registered — the routes don't exist. When provided, all configured strategies become active and the library handles the OAuth callback flow.
298
+
299
+ ### BlobObjectPersistencePort / BlobVariantPersistencePort (Blob Storage)
300
+
301
+ When omitted, blob uploads and deletes work normally, but metadata isn't tracked in your database. When provided, `BlobService` calls the persistence port after each operation so you can maintain your own blob inventory.
302
+
303
+ ### FeatureAccessPort (Payments)
304
+
305
+ When omitted, `FeatureGuard` and `FeatureUsageInterceptor` have no access port and will deny or skip feature checks. When provided, they delegate quota enforcement and usage recording to your adapter.
306
+
307
+ ---
308
+
309
+ ## Common Mistakes
310
+
311
+ **Not calling `super()`** — If you forget `super()` in the constructor, JavaScript throws a runtime error. Abstract classes are still real classes with constructors.
312
+
313
+ **Returning raw Prisma objects** — If your Prisma model includes extra fields beyond what the port interface expects, don't return it raw. Always map to the exact interface shape. Extra fields won't cause type errors but may leak internal data.
314
+
315
+ **Sharing adapters across ports** — Don't make one class implement two different ports. Each port has its own DI token, and NestJS resolves them independently. One class, one port, one responsibility.
316
+
317
+ **Registering instances instead of classes** — `register()` expects the class reference (`PrismaAuthSubjectAdapter`), not `new PrismaAuthSubjectAdapter()`. NestJS creates the instance and injects its dependencies automatically.
@@ -0,0 +1,61 @@
1
+ ---
2
+ title: Guides
3
+ description: Developer guides for integrating and working with Archipel platform libraries.
4
+ ---
5
+
6
+ # Guides
7
+
8
+ Practical guides for working with Archipel packages in your NestJS application.
9
+
10
+ ## Foundations
11
+
12
+ | Guide | What you'll learn |
13
+ | ------------------------------------------ | -------------------------------------------------------------------------------------- |
14
+ | [Getting Started](./getting-started) | Install packages, register your first module, implement ports, and run the app. |
15
+ | [Implementing Ports](./implementing-ports) | How the port/adapter pattern works, how to write adapters, and how to test them. |
16
+ | [Testing](./testing) | Unit testing services, testing port adapters, integration testing with real databases. |
17
+ | [TSDoc Guidelines](./tsdoc-guidelines) | Documentation standards for public APIs and generated reference pages. |
18
+
19
+ ## Security & Identity
20
+
21
+ | Guide | What you'll learn |
22
+ | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
23
+ | [Authentication & Authorization](./authentication-and-authorization) | JWT tokens, role-based access, custom scopes, MFA, sessions, and OAuth social login. |
24
+ | [Cryptography & OTP](./cryptography-and-otp) | Bcrypt password hashing, prefixed UUIDs, and TOTP multi-factor authentication. |
25
+
26
+ ## Data & Storage
27
+
28
+ | Guide | What you'll learn |
29
+ | ----------------------------------------------- | ------------------------------------------------------------------------------------- |
30
+ | [Blob Storage](./blob-storage) | Multi-provider file storage, uploads, signed URLs, and metadata tracking. |
31
+ | [Document Generation](./document-generation) | Generate PDF and DOCX from templates with variable substitution and image processing. |
32
+ | [E-Signing Integration](./esigning-integration) | Electronic signature workflows, provider setup, and webhook handling. |
33
+
34
+ ## Communication & Payments
35
+
36
+ | Guide | What you'll learn |
37
+ | ---------------------------------------------------------- | --------------------------------------------------------------------------------- |
38
+ | [Email Delivery](./email-delivery) | Multi-provider email sending, template engines, and verification flows. |
39
+ | [Payments & Feature Gating](./payments-and-feature-gating) | Payment provider integration, webhook handling, and feature-based access control. |
40
+
41
+ ## Operations & Observability
42
+
43
+ | Guide | What you'll learn |
44
+ | ------------------------------------------------------------ | ------------------------------------------------------------------------------------- |
45
+ | [Telemetry & Observability](./telemetry-and-observability) | OpenTelemetry metrics, distributed tracing, and structured logging. |
46
+ | [Analytics & Error Tracking](./analytics-and-error-tracking) | Capture errors and user context with Sentry, AppInsights, or Datadog. |
47
+ | [Caching](./caching) | In-memory LRU and Redis layered caches with TTL, stale-while-revalidate, and metrics. |
48
+
49
+ ## AI & Extensibility
50
+
51
+ | Guide | What you'll learn |
52
+ | ------------------------------------------ | ------------------------------------------------------------------------------- |
53
+ | [AI Text Generation](./ai-text-generation) | Multi-provider text completions, capability registry, and intent orchestration. |
54
+ | [MCP Server](./mcp-server) | Build MCP servers with tools, resources, and prompts for AI agent integration. |
55
+
56
+ ## Platform Internals
57
+
58
+ | Guide | What you'll learn |
59
+ | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
60
+ | [OpenAPI & Feature Discovery](./openapi-and-feature-discovery) | Multi-document Swagger UI, the @Api decorator, and automatic per-module doc discovery. |
61
+ | [Resource Management](./resource-management) | Load templates, assets, and files from disk, blob storage, or memory via ResourceManager. |
@@ -0,0 +1,222 @@
1
+ ---
2
+ title: MCP Server
3
+ description: Build a Model Context Protocol (MCP) server with tools, resources, and prompts for AI agent integration.
4
+ order: 13
5
+ ---
6
+
7
+ # MCP Server
8
+
9
+ This guide covers building an MCP server with `platform-mcp`: defining tools, resources, and prompts that AI agents can discover and invoke, selecting transports, and registering everything with auto-discovery.
10
+
11
+ ---
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ yarn add @breadstone/archipel-platform-mcp
17
+ ```
18
+
19
+ ---
20
+
21
+ ## What is MCP?
22
+
23
+ The [Model Context Protocol](https://modelcontextprotocol.io/) is an open standard for connecting AI agents to external tools and data sources. An MCP server exposes:
24
+
25
+ - **Tools** — Functions the AI can call (e.g., search a database, create a record)
26
+ - **Resources** — Data the AI can read (e.g., configuration, documentation)
27
+ - **Prompts** — Pre-built prompt templates the AI can use
28
+
29
+ `platform-mcp` provides decorators and a discovery service that auto-registers your tools, resources, and prompts.
30
+
31
+ ---
32
+
33
+ ## Module Registration
34
+
35
+ ```typescript
36
+ import { Module } from '@nestjs/common';
37
+ import { McpModule } from '@breadstone/archipel-platform-mcp';
38
+
39
+ @Module({
40
+ imports: [
41
+ McpModule.register({
42
+ name: 'my-api-mcp',
43
+ version: '1.0.0',
44
+ }),
45
+ ],
46
+ })
47
+ export class AppModule {}
48
+ ```
49
+
50
+ Or asynchronously with configuration:
51
+
52
+ ```typescript
53
+ import { McpModule } from '@breadstone/archipel-platform-mcp';
54
+ import { ConfigService } from '@breadstone/archipel-platform-core';
55
+
56
+ McpModule.registerAsync({
57
+ useFactory: (configService: ConfigService) => ({
58
+ name: configService.get('MCP_SERVER_NAME'),
59
+ version: configService.get('MCP_SERVER_VERSION'),
60
+ }),
61
+ inject: [ConfigService],
62
+ }),
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Defining Tools
68
+
69
+ Use `@McpTool()` to define callable functions:
70
+
71
+ ```typescript
72
+ import { Injectable } from '@nestjs/common';
73
+ import { McpTool } from '@breadstone/archipel-platform-mcp';
74
+
75
+ @Injectable()
76
+ export class UserTools {
77
+ @McpTool({
78
+ name: 'search_users',
79
+ description: 'Search for users by name or email',
80
+ parameters: {
81
+ type: 'object',
82
+ properties: {
83
+ query: { type: 'string', description: 'Search term' },
84
+ limit: { type: 'number', description: 'Max results', default: 10 },
85
+ },
86
+ required: ['query'],
87
+ },
88
+ })
89
+ public async searchUsers(params: { query: string; limit?: number }): Promise<unknown> {
90
+ // Implementation: search your database and return results
91
+ }
92
+
93
+ @McpTool({
94
+ name: 'get_user',
95
+ description: 'Get a user by their ID',
96
+ parameters: {
97
+ type: 'object',
98
+ properties: {
99
+ userId: { type: 'string', description: 'The user ID' },
100
+ },
101
+ required: ['userId'],
102
+ },
103
+ })
104
+ public async getUser(params: { userId: string }): Promise<unknown> {
105
+ // Implementation: fetch a single user
106
+ }
107
+ }
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Defining Resources
113
+
114
+ Use `@McpResource()` to expose data that AI agents can read:
115
+
116
+ ```typescript
117
+ import { Injectable } from '@nestjs/common';
118
+ import { McpResource } from '@breadstone/archipel-platform-mcp';
119
+
120
+ @Injectable()
121
+ export class DocsResources {
122
+ @McpResource({
123
+ name: 'api_documentation',
124
+ description: 'API documentation and usage guidelines',
125
+ uri: 'docs://api/overview',
126
+ })
127
+ public async getApiDocs(): Promise<string> {
128
+ return `
129
+ # API Overview
130
+ Base URL: https://api.yourapp.com/v1
131
+ Authentication: Bearer token required
132
+ Rate limit: 1000 requests/hour
133
+ `;
134
+ }
135
+ }
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Defining Prompts
141
+
142
+ Use `@McpPrompt()` to register reusable prompt templates:
143
+
144
+ ```typescript
145
+ import { Injectable } from '@nestjs/common';
146
+ import { McpPrompt } from '@breadstone/archipel-platform-mcp';
147
+
148
+ @Injectable()
149
+ export class AnalysisPrompts {
150
+ @McpPrompt({
151
+ name: 'analyze_user_activity',
152
+ description: "Analyze a user's recent activity and provide insights",
153
+ parameters: {
154
+ type: 'object',
155
+ properties: {
156
+ userId: { type: 'string', description: 'The user to analyze' },
157
+ timeRange: { type: 'string', description: 'Time range (e.g., 7d, 30d)', default: '7d' },
158
+ },
159
+ required: ['userId'],
160
+ },
161
+ })
162
+ public getTemplate(params: { userId: string; timeRange?: string }): string {
163
+ return `Analyze the recent activity for user ${params.userId} over the last ${params.timeRange ?? '7d'}.
164
+ Provide insights on usage patterns, feature adoption, and potential issues.`;
165
+ }
166
+ }
167
+ ```
168
+
169
+ ---
170
+
171
+ ## Auto-Discovery
172
+
173
+ `McpDiscoveryService` automatically finds and registers all classes that use `@McpTool`, `@McpResource`, or `@McpPrompt` decorators. Just ensure the classes are registered as NestJS providers:
174
+
175
+ ```typescript
176
+ @Module({
177
+ imports: [McpModule.register({ name: 'my-api-mcp', version: '1.0.0' })],
178
+ providers: [UserTools, DocsResources, AnalysisPrompts],
179
+ })
180
+ export class McpFeatureModule {}
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Transport Options
186
+
187
+ MCP supports multiple transport protocols:
188
+
189
+ | Transport | When to use |
190
+ | --------- | --------------------------------------------- |
191
+ | **SSE** | Browser-based AI agents, streaming responses |
192
+ | **HTTP** | Standard REST-based AI agent communication |
193
+ | **Stdio** | CLI tools, local development, piped processes |
194
+
195
+ The `McpServerService` handles transport negotiation automatically.
196
+
197
+ ---
198
+
199
+ ## Connecting the Guides
200
+
201
+ The MCP server can expose Archipel's guides as resources. This makes your documentation discoverable by AI agents:
202
+
203
+ ```typescript
204
+ @Injectable()
205
+ export class GuideResources {
206
+ @McpResource({
207
+ name: 'guide_authentication',
208
+ description: 'Guide for setting up authentication and authorization',
209
+ uri: 'docs://guides/authentication-and-authorization',
210
+ })
211
+ public async getAuthGuide(): Promise<string> {
212
+ // Read and return the guide content
213
+ }
214
+ }
215
+ ```
216
+
217
+ ---
218
+
219
+ ## Next Steps
220
+
221
+ - Browse the [platform-mcp API reference](/packages/platform-mcp/api/) for complete decorator options
222
+ - See the [Getting Started](/guides/getting-started) guide for basic module setup