@hachej/boring-mcp 0.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/README.md +114 -0
- package/dist/front/index.d.ts +51 -0
- package/dist/front/index.js +638 -0
- package/dist/server/index.d.ts +374 -0
- package/dist/server/index.js +1623 -0
- package/dist/shared/index.d.ts +213 -0
- package/dist/shared/index.js +194 -0
- package/package.json +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# `@hachej/boring-mcp`
|
|
2
|
+
|
|
3
|
+
Reusable boring-ui MCP plugin foundation.
|
|
4
|
+
|
|
5
|
+
This package is the generic MCP capability that child apps can enable. It owns:
|
|
6
|
+
|
|
7
|
+
- generic MCP management overlay shell for app-left chrome;
|
|
8
|
+
- provider template, source, tool, policy, redaction, status, and facade contracts;
|
|
9
|
+
- deny-before-allow read-only policy helpers;
|
|
10
|
+
- reusable Composio managed connector provider for hosted OAuth/session onboarding;
|
|
11
|
+
- MCP SDK Streamable HTTP transport for real MCP-compatible endpoints, including Composio session MCP URLs;
|
|
12
|
+
- fake-transport-testable facade seams;
|
|
13
|
+
- normalized tool catalog search/describe contracts;
|
|
14
|
+
- governed `mcp_readonly_call` execution boundary with audit metadata;
|
|
15
|
+
- thin agent bridge tool registry for the seven stable boring-mcp operations;
|
|
16
|
+
- server-only managed connector adapter seam with app-injected secret resolution.
|
|
17
|
+
|
|
18
|
+
It intentionally does **not** own app-specific secret storage or app identity. Apps provide the Composio API key resolver, source persistence, enabled provider config, and actor resolution; boring-mcp owns generic Composio session creation, hosted connect URL creation, MCP protocol transport, catalog, policy, bridge tools, redaction, and read-only execution path.
|
|
19
|
+
|
|
20
|
+
## Enable in an app
|
|
21
|
+
|
|
22
|
+
Apps mount the MCP UI as an app-left management overlay, alongside Plugins and Skills, instead of a Workbench source/panel:
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { BoringMcpSourcesOverlay } from '@hachej/boring-mcp/front'
|
|
26
|
+
|
|
27
|
+
<CoreWorkspaceAgentFront
|
|
28
|
+
appLeftOverlayActions={[{
|
|
29
|
+
id: 'boring-mcp',
|
|
30
|
+
label: 'MCP',
|
|
31
|
+
icon: <McpIcon />,
|
|
32
|
+
render: ({ onClose, headerInsetStart, headerInsetEnd, workspaceId }) => (
|
|
33
|
+
<BoringMcpSourcesOverlay
|
|
34
|
+
options={{ enabledProviderIds: ['notion'], sourceApi: { enabled: true, workspaceId } }}
|
|
35
|
+
onClose={onClose}
|
|
36
|
+
headerInsetStart={headerInsetStart}
|
|
37
|
+
headerInsetEnd={headerInsetEnd}
|
|
38
|
+
/>
|
|
39
|
+
),
|
|
40
|
+
}]}
|
|
41
|
+
/>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Server composition can enable just the prompt, or the full generic bridge tool stack. For hosted Composio-backed sources, the app supplies only source persistence, the server-side API key resolver, enabled provider config, and actor resolution:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import {
|
|
48
|
+
createBoringMcpServerPlugin,
|
|
49
|
+
createComposioManagedConnectorProvider,
|
|
50
|
+
createComposioMcpTransport,
|
|
51
|
+
createManagedConnectorAdapter,
|
|
52
|
+
} from '@hachej/boring-mcp/server'
|
|
53
|
+
|
|
54
|
+
const configs = [
|
|
55
|
+
{ provider: 'notion', displayName: 'Notion', toolkitId: 'notion', connectUrlOrigins: ['https://app.composio.dev'] },
|
|
56
|
+
]
|
|
57
|
+
const secretResolver = {
|
|
58
|
+
async resolveSecret() {
|
|
59
|
+
return { storage: 'server-env' as const, value: process.env.COMPOSIO_API_KEY! }
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const connector = createManagedConnectorAdapter({
|
|
64
|
+
registry: mcpSourceRegistry,
|
|
65
|
+
provider: createComposioManagedConnectorProvider(),
|
|
66
|
+
secretResolver,
|
|
67
|
+
configs,
|
|
68
|
+
redactionCanaries: ['app-owned-mcp-canary'],
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const transport = createComposioMcpTransport({ secretResolver, configs })
|
|
72
|
+
|
|
73
|
+
createCoreWorkspaceAgentServer({
|
|
74
|
+
plugins: [createBoringMcpServerPlugin({
|
|
75
|
+
registry: mcpSourceRegistry,
|
|
76
|
+
transport,
|
|
77
|
+
resolveActor: async (_params, ctx) => resolveActorForAgentSession(ctx.sessionId),
|
|
78
|
+
})],
|
|
79
|
+
})
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
When `registry`, `transport`, and `resolveActor` are provided, the plugin contributes the seven stable agent tools automatically: `mcp_servers_list`, `mcp_server_status`, `mcp_server_doctor`, `mcp_server_probe`, `mcp_tools_search`, `mcp_tool_describe`, and `mcp_readonly_call`.
|
|
83
|
+
|
|
84
|
+
For non-Composio MCP endpoints, apps can still use `createMcpSdkStreamableHttpTransport({ endpoint })` directly.
|
|
85
|
+
|
|
86
|
+
Apps may also list the package in `package.json#boring.defaultPluginPackages` for server/plugin discovery, but shipped app chrome should mount the front overlay explicitly when the UI must render.
|
|
87
|
+
|
|
88
|
+
## Security boundaries
|
|
89
|
+
|
|
90
|
+
Before production provider enablement, apps should record the [Composio security preflight](./docs/composio-security-preflight.md) and run `validateManagedConnectorPreflight` as launch evidence. The runtime `createManagedConnectorAdapter` seam stays small: provider config plus an app-owned server secret resolver; reusable boring-mcp never binds app env/Vault details.
|
|
91
|
+
|
|
92
|
+
- Browser UI never receives provider OAuth tokens, connector API keys, or MCP session headers.
|
|
93
|
+
- Raw provider meta-tools are not exposed by this foundation.
|
|
94
|
+
- Unknown tools are disabled by default.
|
|
95
|
+
- Mutating/admin tool names are denied before any provider call.
|
|
96
|
+
- Provider results pass redaction and secret-leak checks before agent/UI use.
|
|
97
|
+
|
|
98
|
+
## Production launch gate / smoke checklist
|
|
99
|
+
|
|
100
|
+
Before enabling boring-mcp in a shipped app, operators should verify:
|
|
101
|
+
|
|
102
|
+
1. `evaluateBoringMcpLaunchGate` passes for the app composition: plugin id, registry list/get/disconnect, transport, provider templates, all seven bridge tools, timeout, rate/budget gate, readonly input limit, and reviewed docs.
|
|
103
|
+
2. Managed providers pass `validateManagedConnectorPreflight`; app secrets stay server-side and never appear in browser/workspace files.
|
|
104
|
+
3. Source list/status/probe/tool catalog/read-only call responses pass the secret-leak guard using representative OAuth/session canaries.
|
|
105
|
+
4. Provider metadata calls use timeout + retry policy; read-only tool calls use timeout but no automatic retry.
|
|
106
|
+
5. Rate/budget hooks block before provider `listTools`/`callTool` when local limits are exceeded.
|
|
107
|
+
6. Disconnect/revoke is verified through the injected registry status/result and never performs provider tool execution.
|
|
108
|
+
7. Local smoke with a fake managed connector: connect -> status connected -> search tools -> describe tool -> governed readonly call -> disconnect -> verify non-connected status.
|
|
109
|
+
8. Protocol smoke with a fake Streamable HTTP MCP server: real MCP SDK client transport -> list tools -> describe -> governed readonly call -> block mutating tool -> disconnect blocks future call.
|
|
110
|
+
9. Composio smoke with fake Composio HTTP API + fake MCP server: create session -> hosted connect URL -> session MCP headers + server API key on MCP calls -> meta-tool discovery when needed -> search/readonly call -> raw `COMPOSIO_*` meta-tools hidden.
|
|
111
|
+
|
|
112
|
+
## Current status
|
|
113
|
+
|
|
114
|
+
Reusable boring-mcp now includes source handlers, optional launch preflight helpers, generic managed connector adapter seam, reusable Composio managed connector provider, MCP SDK Streamable HTTP transport, normalized tool catalog search/describe, governed read-only execution, exported/generic agent bridge tools, and production launch-gate helpers. Real app secret binding remains app-owned; Constellation-specific code is not required for the generic MCP feature to run against Composio or another MCP-compatible endpoint.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { BoringFrontFactoryWithId } from '@hachej/boring-workspace/plugin';
|
|
3
|
+
import { McpProviderId, McpSourceStatusPayload, McpToolCatalogEntry, McpProviderTemplate } from '../shared/index.js';
|
|
4
|
+
export { AIRTABLE_MCP_TEMPLATE, BORING_MCP_PLUGIN_ID, BORING_MCP_SOURCES_PANEL_ID, BORING_MCP_SOURCES_TAB_PANEL_ID, DEFAULT_MCP_PROVIDER_TEMPLATES, MCP_ERROR_CODES, MCP_TOOL_NAME_PATTERN, McpAccessFacade, McpActor, McpConnectorRef, McpCredentialProvider, McpDiscoveredResource, McpDiscoveredTool, McpDoctorIssue, McpDoctorResult, McpError, McpErrorCode, McpProbeResult, McpReadonlyCallAuditEvent, McpReadonlyCallInput, McpReadonlyCallResult, McpSource, McpSourceAccessPolicy, McpSourceDto, McpSourceOwnerKind, McpSourceRegistry, McpSourceStatus, McpSourceStore, McpToolCallResult, McpToolDecision, McpToolDescribeResult, McpToolRisk, McpToolSearchResult, McpTransport, McpTransportClient, McpTransportListToolsOptions, NOTION_MCP_TEMPLATE, NormalizedMcpTool, assertMcpToolAllowed, classifyMcpTool, classifyMcpTools, containsMcpCanary, containsMcpSecret, containsMcpSecretOrCanary, doctorMcpSource, getMcpProviderTemplate, redactMcpSecrets, toMcpSourceDto, validateMcpToolName } from '../shared/index.js';
|
|
5
|
+
|
|
6
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
7
|
+
type BoringMcpSourceActionResult = McpSourceStatusPayload | void;
|
|
8
|
+
interface BoringMcpSourceActions {
|
|
9
|
+
onConnect?: (providerId: McpProviderId) => MaybePromise<BoringMcpSourceActionResult>;
|
|
10
|
+
onRefreshStatus?: (sourceId: string, providerId: McpProviderId) => MaybePromise<BoringMcpSourceActionResult>;
|
|
11
|
+
onDisconnect?: (sourceId: string, providerId: McpProviderId) => MaybePromise<BoringMcpSourceActionResult>;
|
|
12
|
+
onViewTools?: (sourceId: string, providerId: McpProviderId) => MaybePromise<void>;
|
|
13
|
+
onListTools?: (sourceId: string, providerId: McpProviderId, refresh?: boolean) => MaybePromise<McpToolCatalogEntry[]>;
|
|
14
|
+
}
|
|
15
|
+
interface BoringMcpProviderSetupState {
|
|
16
|
+
providerId: McpProviderId;
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
message?: string;
|
|
19
|
+
}
|
|
20
|
+
interface BoringMcpSourceApiOptions {
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
baseUrl?: string;
|
|
23
|
+
workspaceId?: string;
|
|
24
|
+
resolveWorkspaceId?: () => string | undefined;
|
|
25
|
+
openConnectUrl?: (url: string) => void;
|
|
26
|
+
}
|
|
27
|
+
interface CreateBoringMcpPluginOptions {
|
|
28
|
+
label?: string;
|
|
29
|
+
tabTitle?: string;
|
|
30
|
+
providers?: readonly McpProviderTemplate[];
|
|
31
|
+
enabledProviderIds?: readonly string[];
|
|
32
|
+
sourceStatuses?: readonly McpSourceStatusPayload[];
|
|
33
|
+
sourceActions?: BoringMcpSourceActions;
|
|
34
|
+
sourceApi?: BoringMcpSourceApiOptions;
|
|
35
|
+
providerSetup?: readonly BoringMcpProviderSetupState[];
|
|
36
|
+
connectionUnavailableMessage?: string;
|
|
37
|
+
}
|
|
38
|
+
declare function BoringMcpSourcesPanel({ options }: {
|
|
39
|
+
options: CreateBoringMcpPluginOptions;
|
|
40
|
+
}): react.JSX.Element;
|
|
41
|
+
interface BoringMcpSourcesOverlayProps {
|
|
42
|
+
options?: CreateBoringMcpPluginOptions;
|
|
43
|
+
onClose?: () => void;
|
|
44
|
+
headerInsetStart?: boolean;
|
|
45
|
+
headerInsetEnd?: boolean;
|
|
46
|
+
}
|
|
47
|
+
declare function BoringMcpSourcesOverlay({ options, onClose, headerInsetStart, headerInsetEnd }: BoringMcpSourcesOverlayProps): react.JSX.Element;
|
|
48
|
+
declare function createBoringMcpPlugin(options?: CreateBoringMcpPluginOptions): BoringFrontFactoryWithId;
|
|
49
|
+
declare const boringMcpPlugin: BoringFrontFactoryWithId;
|
|
50
|
+
|
|
51
|
+
export { type BoringMcpProviderSetupState, type BoringMcpSourceActionResult, type BoringMcpSourceActions, type BoringMcpSourceApiOptions, BoringMcpSourcesOverlay, type BoringMcpSourcesOverlayProps, BoringMcpSourcesPanel, type CreateBoringMcpPluginOptions, McpProviderId, McpProviderTemplate, McpSourceStatusPayload, McpToolCatalogEntry, createBoringMcpPlugin, boringMcpPlugin as default };
|