FrontMCP Extensibility
Patterns and examples for extending FrontMCP servers with external npm packages. The core SDK handles MCP protocol, DI, and lifecycle — this skill shows how to integrate third-party libraries as providers and tools.
When to Use This Skill
Must Use
- Adding semantic search or similarity matching to your server (VectoriaDB)
- Integrating an external npm package as a FrontMCP provider
- Building tools that wrap third-party services (databases, APIs, ML models)
Recommended
- Looking for patterns to structure external service integrations
- Deciding between provider-based vs direct integration for a library
- Adding capabilities like applescript automation, VM execution, or data processing
Skip When
- You need to build core MCP components (see
frontmcp-development)
- You need to configure auth, transport, or CORS (see
frontmcp-config)
- You need to write a plugin with hooks and context extensions (see
create-plugin)
Decision: Use this skill when integrating external libraries into your FrontMCP server as providers or tools.
Prerequisites
- A FrontMCP project (see
frontmcp-setup if you don't have one).
- The external library installed as a runtime
dependency (not devDependency).
- Familiarity with FrontMCP providers and tools (see
create-provider, create-tool).
Steps
- Pick the integration shape — provider for stateful clients (DB, search index), tool-only for stateless one-shot calls.
- Wrap the library in a provider — declare a typed DI token and a
@Provider class so consumers depend on the boundary, not the library.
- Register it — add to
@App({ providers: [...] }) or @FrontMcp({ providers: [...] }).
- Expose via tools/resources — call
this.get(TOKEN) in ToolContext/ResourceContext; never import the library directly from the tool.
- Handle errors at the boundary — translate library-specific errors into
PublicMcpError/InvalidInputError so MCP clients see structured failures.
Scenario Routing Table
| Scenario |
Reference |
Description |
| Add in-memory semantic search with VectoriaDB |
references/vectoriadb.md |
TF-IDF or ML semantic indexing, provider+tool pattern |
| Add tamper-evident skill audit logging |
references/skill-audit-log.md |
Hash-chained, signed audit records for skill executions |
| Load an app from an npm package |
multi-app-composition (in frontmcp-setup) |
App.esm('@scope/pkg@^1.0.0', 'AppName') pattern |
| Connect to a remote MCP server |
multi-app-composition (in frontmcp-setup) |
App.remote('https://...', 'ns') pattern |
| Build a reusable plugin with hooks |
create-plugin-hooks (in frontmcp-development) |
DynamicPlugin, context extensions, lifecycle hooks |
| Build a custom adapter for an external source |
create-adapter (in frontmcp-development) |
DynamicAdapter for OpenAPI, GraphQL, or custom sources |
| Auto-generate tools from an OpenAPI spec |
official-adapters (in frontmcp-development) |
OpenapiAdapter with filtering, auth, and transforms |
Integration Pattern
The standard pattern for integrating any external library:
- Create a provider — wraps the library as a singleton or scoped service
- Register the provider — add to
@App({ providers: [...] }) or @FrontMcp({ providers: [...] })
- Create tools — expose the provider's capabilities as MCP tools via
this.get(ProviderClass) (the class itself is the DI token)
- Optionally create resources — expose data as MCP resources with autocompletion
// 1. Provider wraps the library (the class itself is the DI token)
@Provider({ name: 'my-search', scope: ProviderScope.GLOBAL })
export class SearchProvider {
private client: ExternalLibrary;
constructor() {
this.client = new ExternalLibrary({
/* config */
});
}
async search(query: string) {
return this.client.query(query);
}
}
// 2. Tool exposes it
@Tool({ name: 'search', inputSchema: { query: z.string() } })
export default class SearchTool extends ToolContext {
async execute(input: { query: string }) {
return this.get(SearchProvider).search(input.query);
}
}
Available Integrations
| Library |
Purpose |
Reference |
| VectoriaDB |
In-memory TF-IDF semantic search |
references/vectoriadb.md |
| Skill audit log |
Tamper-evident hash-chained audit log for skill runs |
references/skill-audit-log.md |
More integrations can be added as references (e.g., enclave-vm, applescript, database clients).
Common Patterns
| Pattern |
Correct |
Incorrect |
Why |
| Library access |
this.get(SearchToken) from a tool |
import { client } from 'lib' in a tool |
DI boundary lets you swap implementations and test in isolation |
| Provider scope |
ProviderScope.GLOBAL for shared clients |
New instance per request |
Library clients (DB pools, indices) are expensive to construct |
| Async initialisation |
onInit() lifecycle hook on the provider |
Constructor await |
Constructors can't be async; onInit is the framework's init seam |
| Error surfaces |
Throw PublicMcpError/InvalidInputError |
Re-throw raw library errors |
Library stack traces leak internals and aren't JSON-RPC error-coded |
Verification Checklist
Troubleshooting
| Problem |
Cause |
Solution |
Cannot find module '<lib>' at runtime |
Library declared as devDependency only |
Move to dependencies; rebuild the bundle if deploying as MCPB/CLI |
| Provider constructed once per request |
Default scope used; expensive client recreated each call |
Set scope: ProviderScope.GLOBAL on the @Provider decorator |
Tool sees undefined from this.get(TOKEN) |
Provider not registered in the active @App/@FrontMcp scope |
Add the provider class to the scope's providers: [...] array |
| Browser build fails with Node-only library |
Library uses node: modules not available at the target |
Gate behind availableWhen.platform, or move the integration into a server-only app and call it via a remote transport |
Examples
Each reference has matching examples under examples/<reference>/:
vectoriadb
| Example |
Level |
Description |
product-catalog-search |
Advanced |
Shows advanced VectoriaDB usage with typed document metadata, batch operations, filtered search by multiple criteria, and batch indexing of a product catalog. |
semantic-search-with-persistence |
Intermediate |
Shows how to use VectoriaDB for semantic search with transformer models, filtered search, and FileStorageAdapter for persistence across restarts. |
tfidf-keyword-search |
Basic |
Shows how to use TFIDFVectoria for zero-dependency keyword search in a FrontMCP provider, with field weights and index building. |
Accessing This Skill
Skills are distributed as plain SKILL.md files plus a sibling references/
and examples/ tree, so consumers can pick whichever access mode fits:
| Mode |
How it works |
| Filesystem |
Read libs/skills/catalog/frontmcp-extensibility/ directly from a clone of the catalog repo, or from a published @frontmcp/skills install. SKILL.md is the entry point. |
frontmcp CLI |
frontmcp skills list, frontmcp skills read frontmcp-extensibility, frontmcp skills read frontmcp-extensibility:references/<file>.md, frontmcp skills install frontmcp-extensibility — no server required. |
MCP skill:// |
When a developer mounts this skill into their own FrontMCP server (@FrontMcp({ skills: [...] })), the SDK exposes it via SEP-2640 resources: skill://frontmcp-extensibility/SKILL.md, skill://frontmcp-extensibility/references/{file}.md, etc. The server’s skill://index.json returns the SEP-2640 discovery document for everything mounted on it. |
The catalog itself is not an MCP server. The skill:// URIs only resolve
when a server has been configured to host this skill.
Reference
- Related skills:
create-provider, create-tool, frontmcp-development
1---2name: frontmcp-extensibility3description: Use when extending FrontMCP beyond the core SDK by integrating external npm packages, libraries, or third-party services into providers and tools. Covers VectoriaDB for in-memory semantic and vector search (ML-based embeddings or TF-IDF keyword engines, with persistence) and the tamper-evident, hash-chained skill audit log (pluggable signer and store, with chain verification). Triggers: add semantic search, vector search, embeddings, similarity search, recommendations, ML features, audit logging, or integrate an external library, database, or API beyond the built-in SDK.4license: Apache-2.05---67# FrontMCP Extensibility89Patterns and examples for extending FrontMCP servers with external npm packages. The core SDK handles MCP protocol, DI, and lifecycle — this skill shows how to integrate third-party libraries as providers and tools.1011## When to Use This Skill1213### Must Use1415- Adding semantic search or similarity matching to your server (VectoriaDB)16- Integrating an external npm package as a FrontMCP provider17- Building tools that wrap third-party services (databases, APIs, ML models)1819### Recommended2021- Looking for patterns to structure external service integrations22- Deciding between provider-based vs direct integration for a library23- Adding capabilities like applescript automation, VM execution, or data processing2425### Skip When2627- You need to build core MCP components (see `frontmcp-development`)28- You need to configure auth, transport, or CORS (see `frontmcp-config`)29- You need to write a plugin with hooks and context extensions (see `create-plugin`)3031> **Decision:** Use this skill when integrating external libraries into your FrontMCP server as providers or tools.3233## Prerequisites3435- A FrontMCP project (see `frontmcp-setup` if you don't have one).36- The external library installed as a runtime `dependency` (not `devDependency`).37- Familiarity with FrontMCP providers and tools (see `create-provider`, `create-tool`).3839## Steps40411. **Pick the integration shape** — provider for stateful clients (DB, search index), tool-only for stateless one-shot calls.422. **Wrap the library in a provider** — declare a typed DI token and a `@Provider` class so consumers depend on the boundary, not the library.433. **Register it** — add to `@App({ providers: [...] })` or `@FrontMcp({ providers: [...] })`.444. **Expose via tools/resources** — call `this.get(TOKEN)` in `ToolContext`/`ResourceContext`; never import the library directly from the tool.455. **Handle errors at the boundary** — translate library-specific errors into `PublicMcpError`/`InvalidInputError` so MCP clients see structured failures.4647## Scenario Routing Table4849| Scenario | Reference | Description |50| --------------------------------------------- | ----------------------------------------------- | -------------------------------------------------------- |51| Add in-memory semantic search with VectoriaDB | `references/vectoriadb.md` | TF-IDF or ML semantic indexing, provider+tool pattern |52| Add tamper-evident skill audit logging | `references/skill-audit-log.md` | Hash-chained, signed audit records for skill executions |53| Load an app from an npm package | `multi-app-composition` (in frontmcp-setup) | `App.esm('@scope/pkg@^1.0.0', 'AppName')` pattern |54| Connect to a remote MCP server | `multi-app-composition` (in frontmcp-setup) | `App.remote('https://...', 'ns')` pattern |55| Build a reusable plugin with hooks | `create-plugin-hooks` (in frontmcp-development) | `DynamicPlugin`, context extensions, lifecycle hooks |56| Build a custom adapter for an external source | `create-adapter` (in frontmcp-development) | `DynamicAdapter` for OpenAPI, GraphQL, or custom sources |57| Auto-generate tools from an OpenAPI spec | `official-adapters` (in frontmcp-development) | `OpenapiAdapter` with filtering, auth, and transforms |5859## Integration Pattern6061The standard pattern for integrating any external library:62631. **Create a provider** — wraps the library as a singleton or scoped service642. **Register the provider** — add to `@App({ providers: [...] })` or `@FrontMcp({ providers: [...] })`653. **Create tools** — expose the provider's capabilities as MCP tools via `this.get(ProviderClass)` (the class itself is the DI token)664. **Optionally create resources** — expose data as MCP resources with autocompletion6768```typescript69// 1. Provider wraps the library (the class itself is the DI token)70@Provider({ name: 'my-search', scope: ProviderScope.GLOBAL })71export class SearchProvider {72 private client: ExternalLibrary;73 constructor() {74 this.client = new ExternalLibrary({75 /* config */76 });77 }78 async search(query: string) {79 return this.client.query(query);80 }81}8283// 2. Tool exposes it84@Tool({ name: 'search', inputSchema: { query: z.string() } })85export default class SearchTool extends ToolContext {86 async execute(input: { query: string }) {87 return this.get(SearchProvider).search(input.query);88 }89}90```9192## Available Integrations9394| Library | Purpose | Reference |95| ------------------- | ---------------------------------------------------- | ------------------------------- |96| **VectoriaDB** | In-memory TF-IDF semantic search | `references/vectoriadb.md` |97| **Skill audit log** | Tamper-evident hash-chained audit log for skill runs | `references/skill-audit-log.md` |9899More integrations can be added as references (e.g., enclave-vm, applescript, database clients).100101## Common Patterns102103| Pattern | Correct | Incorrect | Why |104| -------------------- | ------------------------------------------ | ---------------------------------------- | ------------------------------------------------------------------- |105| Library access | `this.get(SearchToken)` from a tool | `import { client } from 'lib'` in a tool | DI boundary lets you swap implementations and test in isolation |106| Provider scope | `ProviderScope.GLOBAL` for shared clients | New instance per request | Library clients (DB pools, indices) are expensive to construct |107| Async initialisation | `onInit()` lifecycle hook on the provider | Constructor `await` | Constructors can't be async; `onInit` is the framework's init seam |108| Error surfaces | Throw `PublicMcpError`/`InvalidInputError` | Re-throw raw library errors | Library stack traces leak internals and aren't JSON-RPC error-coded |109110## Verification Checklist111112- [ ] External library is in `dependencies` (not `devDependencies`)113- [ ] Provider wraps the library with proper initialization and cleanup114- [ ] Provider class is listed in `@App` or `@FrontMcp` `providers: [...]` array (the class itself is the DI token)115- [ ] Tools use `this.get(ProviderClass)` to access the provider (not direct imports)116- [ ] Error handling wraps library-specific errors into MCP error classes117118## Troubleshooting119120| Problem | Cause | Solution |121| -------------------------------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |122| `Cannot find module '<lib>'` at runtime | Library declared as `devDependency` only | Move to `dependencies`; rebuild the bundle if deploying as MCPB/CLI |123| Provider constructed once per request | Default scope used; expensive client recreated each call | Set `scope: ProviderScope.GLOBAL` on the `@Provider` decorator |124| Tool sees `undefined` from `this.get(TOKEN)` | Provider not registered in the active `@App`/`@FrontMcp` scope | Add the provider class to the scope's `providers: [...]` array |125| Browser build fails with Node-only library | Library uses `node:` modules not available at the target | Gate behind `availableWhen.platform`, or move the integration into a server-only app and call it via a remote transport |126127## Examples128129Each reference has matching examples under [`examples/<reference>/`](./examples/):130131### `vectoriadb`132133| Example | Level | Description |134| ----------------------------------------------------------------------------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |135| [`product-catalog-search`](./examples/vectoriadb/product-catalog-search.md) | Advanced | Shows advanced VectoriaDB usage with typed document metadata, batch operations, filtered search by multiple criteria, and batch indexing of a product catalog. |136| [`semantic-search-with-persistence`](./examples/vectoriadb/semantic-search-with-persistence.md) | Intermediate | Shows how to use `VectoriaDB` for semantic search with transformer models, filtered search, and `FileStorageAdapter` for persistence across restarts. |137| [`tfidf-keyword-search`](./examples/vectoriadb/tfidf-keyword-search.md) | Basic | Shows how to use `TFIDFVectoria` for zero-dependency keyword search in a FrontMCP provider, with field weights and index building. |138139## Accessing This Skill140141Skills are distributed as plain SKILL.md files plus a sibling `references/`142and `examples/` tree, so consumers can pick whichever access mode fits:143144| Mode | How it works |145| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |146| **Filesystem** | Read `libs/skills/catalog/frontmcp-extensibility/` directly from a clone of the catalog repo, or from a published `@frontmcp/skills` install. SKILL.md is the entry point. |147| **`frontmcp` CLI** | `frontmcp skills list`, `frontmcp skills read frontmcp-extensibility`, `frontmcp skills read frontmcp-extensibility:references/<file>.md`, `frontmcp skills install frontmcp-extensibility` — no server required. |148| **MCP `skill://`** | When a developer mounts this skill into their own FrontMCP server (`@FrontMcp({ skills: [...] })`), the SDK exposes it via SEP-2640 resources: `skill://frontmcp-extensibility/SKILL.md`, `skill://frontmcp-extensibility/references/{file}.md`, etc. The server’s `skill://index.json` returns the SEP-2640 discovery document for everything mounted on it. |149150The catalog itself is **not** an MCP server. The `skill://` URIs only resolve151when a server has been configured to host this skill.152153## Reference154155- Related skills: `create-provider`, `create-tool`, `frontmcp-development`