mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-14 23:07:29 +00:00
Add LogicSRC standards MCP server
This commit is contained in:
parent
4e4c78140d
commit
dd150f391a
26 changed files with 2250 additions and 15 deletions
|
|
@ -12,6 +12,7 @@ apps/
|
|||
commandboard-web PWA shell
|
||||
packages/
|
||||
cli commandboard/cb command line client
|
||||
logicsrc-mcp @profullstack/logicsrc-mcp standards MCP server
|
||||
tui terminal UI
|
||||
schemas LogicSRC JSON schemas
|
||||
validators schema validation utilities
|
||||
|
|
@ -33,8 +34,15 @@ npm install
|
|||
npm run check
|
||||
npm --workspace @logicsrc/cli run dev -- plugins
|
||||
npm --workspace @logicsrc/cli run dev -- tui
|
||||
npm --workspace @profullstack/logicsrc-mcp run build
|
||||
node packages/logicsrc-mcp/dist/index.js
|
||||
```
|
||||
|
||||
## MCP
|
||||
|
||||
LogicSRC exposes a standards-focused MCP server as `@profullstack/logicsrc-mcp`.
|
||||
It provides read-only resources for docs and schemas, validation/example tools, and prompt templates for creating LogicSRC-compatible documents.
|
||||
|
||||
## v1.0.0 Priorities
|
||||
|
||||
- LogicSRC task, agent, run, event, permission, and plugin schemas.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#151515" />
|
||||
<link rel="manifest" href="/manifest.webmanifest" />
|
||||
<link rel="stylesheet" href="/src/styles.css" />
|
||||
<title>CommandBoard.run</title>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"name": "CommandBoard.run",
|
||||
"short_name": "CommandBoard",
|
||||
"description": "A modern BBS for humans and AI agents.",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#f7f2ea",
|
||||
"theme_color": "#151515",
|
||||
"icons": []
|
||||
}
|
||||
|
|
@ -4,11 +4,13 @@
|
|||
"description": "CommandBoard.run PWA shell.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "node scripts/check-assets.js",
|
||||
"build": "node scripts/check-assets.js && vite build",
|
||||
"dev": "vite --host 0.0.0.0",
|
||||
"start": "node server.js",
|
||||
"test:e2e": "playwright test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logicsrc/commandboard-api": "file:../commandboard-api",
|
||||
"@vitejs/plugin-react": "^5.1.1",
|
||||
"vite": "^7.2.6",
|
||||
"typescript": "^5.9.3"
|
||||
|
|
|
|||
5
apps/commandboard-web/public/icon.svg
Normal file
5
apps/commandboard-web/public/icon.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-label="CommandBoard.run">
|
||||
<rect width="512" height="512" rx="72" fill="#151515"/>
|
||||
<path fill="#f0c56a" d="M104 116h304v64H104zM104 224h192v64H104zM104 332h304v64H104z"/>
|
||||
<path fill="#5ac8a6" d="M328 214h80v84h-80z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 308 B |
18
apps/commandboard-web/public/manifest.webmanifest
Normal file
18
apps/commandboard-web/public/manifest.webmanifest
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "CommandBoard.run",
|
||||
"short_name": "CommandBoard",
|
||||
"description": "LogicSRC command board for humans and AI agents.",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#f7f2ea",
|
||||
"theme_color": "#151515",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icon.svg",
|
||||
"sizes": "any",
|
||||
"type": "image/svg+xml",
|
||||
"purpose": "any maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
32
apps/commandboard-web/public/service-worker.js
Normal file
32
apps/commandboard-web/public/service-worker.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
const CACHE_NAME = "commandboard-shell-v1";
|
||||
const SHELL_ASSETS = ["/", "/manifest.webmanifest", "/icon.svg"];
|
||||
|
||||
self.addEventListener("install", (event) => {
|
||||
event.waitUntil(caches.open(CACHE_NAME).then((cache) => cache.addAll(SHELL_ASSETS)));
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener("activate", (event) => {
|
||||
event.waitUntil(
|
||||
caches.keys().then((keys) => Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key))))
|
||||
);
|
||||
self.clients.claim();
|
||||
});
|
||||
|
||||
self.addEventListener("fetch", (event) => {
|
||||
if (event.request.method !== "GET") {
|
||||
return;
|
||||
}
|
||||
|
||||
event.respondWith(
|
||||
fetch(event.request)
|
||||
.then((response) => {
|
||||
if (response.ok && new URL(event.request.url).origin === self.location.origin) {
|
||||
const clone = response.clone();
|
||||
caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone));
|
||||
}
|
||||
return response;
|
||||
})
|
||||
.catch(() => caches.match(event.request).then((cached) => cached || caches.match("/")))
|
||||
);
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { accessSync } from "node:fs";
|
||||
|
||||
for (const file of ["index.html", "manifest.webmanifest", "src/main.ts", "src/styles.css"]) {
|
||||
for (const file of ["index.html", "public/manifest.webmanifest", "public/icon.svg", "public/service-worker.js", "src/main.ts", "src/styles.css"]) {
|
||||
accessSync(new URL(`../${file}`, import.meta.url));
|
||||
}
|
||||
|
||||
|
|
|
|||
89
apps/commandboard-web/server.js
Normal file
89
apps/commandboard-web/server.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import { createReadStream, existsSync, statSync } from "node:fs";
|
||||
import { createServer } from "node:http";
|
||||
import { extname, join, normalize, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { createCommandBoardServer } from "../commandboard-api/dist/index.js";
|
||||
|
||||
const appDirectory = fileURLToPath(new URL(".", import.meta.url));
|
||||
const distDirectory = resolve(appDirectory, "dist");
|
||||
const indexFile = join(distDirectory, "index.html");
|
||||
const apiServer = createCommandBoardServer();
|
||||
const port = Number(process.env.PORT ?? 4173);
|
||||
|
||||
const mimeTypes = {
|
||||
".css": "text/css; charset=utf-8",
|
||||
".html": "text/html; charset=utf-8",
|
||||
".ico": "image/x-icon",
|
||||
".js": "text/javascript; charset=utf-8",
|
||||
".json": "application/json; charset=utf-8",
|
||||
".png": "image/png",
|
||||
".svg": "image/svg+xml",
|
||||
".webmanifest": "application/manifest+json; charset=utf-8"
|
||||
};
|
||||
|
||||
createServer((request, response) => {
|
||||
const url = new URL(request.url ?? "/", `http://${request.headers.host ?? "localhost"}`);
|
||||
|
||||
if (url.pathname === "/health" || url.pathname.startsWith("/api/")) {
|
||||
apiServer.emit("request", request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.method !== "GET" && request.method !== "HEAD") {
|
||||
response.writeHead(405, { allow: "GET, HEAD" });
|
||||
response.end("Method not allowed");
|
||||
return;
|
||||
}
|
||||
|
||||
const file = resolveStaticPath(url.pathname);
|
||||
if (!file) {
|
||||
response.writeHead(403);
|
||||
response.end("Forbidden");
|
||||
return;
|
||||
}
|
||||
|
||||
sendFile(file, request.method === "HEAD", response);
|
||||
}).listen(port, () => {
|
||||
console.log(`CommandBoard.run PWA listening on http://localhost:${port}`);
|
||||
});
|
||||
|
||||
function resolveStaticPath(pathname) {
|
||||
const decodedPath = decodeURIComponent(pathname);
|
||||
const normalizedPath = normalize(decodedPath).replace(/^(\.\.[/\\])+/, "");
|
||||
let candidate = join(distDirectory, normalizedPath);
|
||||
|
||||
if (!candidate.startsWith(distDirectory)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (existsSync(candidate) && statSync(candidate).isDirectory()) {
|
||||
candidate = join(candidate, "index.html");
|
||||
}
|
||||
|
||||
if (existsSync(candidate) && statSync(candidate).isFile()) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
return indexFile;
|
||||
}
|
||||
|
||||
function sendFile(file, headOnly, response) {
|
||||
if (!existsSync(file)) {
|
||||
response.writeHead(500, { "content-type": "text/plain; charset=utf-8" });
|
||||
response.end("Build output missing. Run `npm run build` before `npm start`.");
|
||||
return;
|
||||
}
|
||||
|
||||
const extension = extname(file);
|
||||
response.writeHead(200, {
|
||||
"cache-control": extension === ".html" ? "no-store" : "public, max-age=31536000, immutable",
|
||||
"content-type": mimeTypes[extension] ?? "application/octet-stream"
|
||||
});
|
||||
|
||||
if (headOnly) {
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
|
||||
createReadStream(file).pipe(response);
|
||||
}
|
||||
|
|
@ -101,3 +101,9 @@ document.querySelector<HTMLDivElement>("#app")!.innerHTML = `
|
|||
</section>
|
||||
</main>
|
||||
`;
|
||||
|
||||
if ("serviceWorker" in navigator) {
|
||||
window.addEventListener("load", () => {
|
||||
navigator.serviceWorker.register("/service-worker.js").catch(() => undefined);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
14
apps/logicsrc-web/index.html
Normal file
14
apps/logicsrc-web/index.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#101418" />
|
||||
<link rel="manifest" href="/manifest.webmanifest" />
|
||||
<title>LogicSRC</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
16
apps/logicsrc-web/package.json
Normal file
16
apps/logicsrc-web/package.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "@logicsrc/web",
|
||||
"version": "0.1.0",
|
||||
"description": "LogicSRC standards and open specification PWA.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "node scripts/check-assets.js && vite build",
|
||||
"dev": "vite --host 0.0.0.0",
|
||||
"start": "node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logicsrc/commandboard-api": "file:../commandboard-api",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "^7.2.6"
|
||||
}
|
||||
}
|
||||
5
apps/logicsrc-web/public/icon.svg
Normal file
5
apps/logicsrc-web/public/icon.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-label="LogicSRC">
|
||||
<rect width="512" height="512" rx="72" fill="#101418"/>
|
||||
<path fill="#5ac8a6" d="M96 126h96v96H96zM224 126h192v48H224zM224 198h144v48H224z"/>
|
||||
<path fill="#f0c56a" d="M96 290h320v48H96zM96 362h240v48H96z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 314 B |
18
apps/logicsrc-web/public/manifest.webmanifest
Normal file
18
apps/logicsrc-web/public/manifest.webmanifest
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "LogicSRC",
|
||||
"short_name": "LogicSRC",
|
||||
"description": "Open standards and schemas for human and AI agent coordination.",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#f6f7f4",
|
||||
"theme_color": "#101418",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icon.svg",
|
||||
"sizes": "any",
|
||||
"type": "image/svg+xml",
|
||||
"purpose": "any maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
32
apps/logicsrc-web/public/service-worker.js
Normal file
32
apps/logicsrc-web/public/service-worker.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
const CACHE_NAME = "logicsrc-standards-v1";
|
||||
const SHELL_ASSETS = ["/", "/manifest.webmanifest", "/icon.svg"];
|
||||
|
||||
self.addEventListener("install", (event) => {
|
||||
event.waitUntil(caches.open(CACHE_NAME).then((cache) => cache.addAll(SHELL_ASSETS)));
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener("activate", (event) => {
|
||||
event.waitUntil(
|
||||
caches.keys().then((keys) => Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key))))
|
||||
);
|
||||
self.clients.claim();
|
||||
});
|
||||
|
||||
self.addEventListener("fetch", (event) => {
|
||||
if (event.request.method !== "GET") {
|
||||
return;
|
||||
}
|
||||
|
||||
event.respondWith(
|
||||
fetch(event.request)
|
||||
.then((response) => {
|
||||
if (response.ok && new URL(event.request.url).origin === self.location.origin) {
|
||||
const clone = response.clone();
|
||||
caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone));
|
||||
}
|
||||
return response;
|
||||
})
|
||||
.catch(() => caches.match(event.request).then((cached) => cached || caches.match("/")))
|
||||
);
|
||||
});
|
||||
7
apps/logicsrc-web/scripts/check-assets.js
Normal file
7
apps/logicsrc-web/scripts/check-assets.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { accessSync } from "node:fs";
|
||||
|
||||
for (const file of ["index.html", "public/manifest.webmanifest", "public/icon.svg", "public/service-worker.js", "src/main.ts", "src/styles.css"]) {
|
||||
accessSync(new URL(`../${file}`, import.meta.url));
|
||||
}
|
||||
|
||||
console.log("logicsrc-web assets verified");
|
||||
89
apps/logicsrc-web/server.js
Normal file
89
apps/logicsrc-web/server.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import { createReadStream, existsSync, statSync } from "node:fs";
|
||||
import { createServer } from "node:http";
|
||||
import { extname, join, normalize, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { createCommandBoardServer } from "../commandboard-api/dist/index.js";
|
||||
|
||||
const appDirectory = fileURLToPath(new URL(".", import.meta.url));
|
||||
const distDirectory = resolve(appDirectory, "dist");
|
||||
const indexFile = join(distDirectory, "index.html");
|
||||
const apiServer = createCommandBoardServer();
|
||||
const port = Number(process.env.PORT ?? 4174);
|
||||
|
||||
const mimeTypes = {
|
||||
".css": "text/css; charset=utf-8",
|
||||
".html": "text/html; charset=utf-8",
|
||||
".ico": "image/x-icon",
|
||||
".js": "text/javascript; charset=utf-8",
|
||||
".json": "application/json; charset=utf-8",
|
||||
".png": "image/png",
|
||||
".svg": "image/svg+xml",
|
||||
".webmanifest": "application/manifest+json; charset=utf-8"
|
||||
};
|
||||
|
||||
createServer((request, response) => {
|
||||
const url = new URL(request.url ?? "/", `http://${request.headers.host ?? "localhost"}`);
|
||||
|
||||
if (url.pathname === "/health" || url.pathname.startsWith("/api/")) {
|
||||
apiServer.emit("request", request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.method !== "GET" && request.method !== "HEAD") {
|
||||
response.writeHead(405, { allow: "GET, HEAD" });
|
||||
response.end("Method not allowed");
|
||||
return;
|
||||
}
|
||||
|
||||
const file = resolveStaticPath(url.pathname);
|
||||
if (!file) {
|
||||
response.writeHead(403);
|
||||
response.end("Forbidden");
|
||||
return;
|
||||
}
|
||||
|
||||
sendFile(file, request.method === "HEAD", response);
|
||||
}).listen(port, () => {
|
||||
console.log(`LogicSRC standards PWA listening on http://localhost:${port}`);
|
||||
});
|
||||
|
||||
function resolveStaticPath(pathname) {
|
||||
const decodedPath = decodeURIComponent(pathname);
|
||||
const normalizedPath = normalize(decodedPath).replace(/^(\.\.[/\\])+/, "");
|
||||
let candidate = join(distDirectory, normalizedPath);
|
||||
|
||||
if (!candidate.startsWith(distDirectory)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (existsSync(candidate) && statSync(candidate).isDirectory()) {
|
||||
candidate = join(candidate, "index.html");
|
||||
}
|
||||
|
||||
if (existsSync(candidate) && statSync(candidate).isFile()) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
return indexFile;
|
||||
}
|
||||
|
||||
function sendFile(file, headOnly, response) {
|
||||
if (!existsSync(file)) {
|
||||
response.writeHead(500, { "content-type": "text/plain; charset=utf-8" });
|
||||
response.end("Build output missing. Run `npm run build` before `npm start`.");
|
||||
return;
|
||||
}
|
||||
|
||||
const extension = extname(file);
|
||||
response.writeHead(200, {
|
||||
"cache-control": extension === ".html" ? "no-store" : "public, max-age=31536000, immutable",
|
||||
"content-type": mimeTypes[extension] ?? "application/octet-stream"
|
||||
});
|
||||
|
||||
if (headOnly) {
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
|
||||
createReadStream(file).pipe(response);
|
||||
}
|
||||
121
apps/logicsrc-web/src/main.ts
Normal file
121
apps/logicsrc-web/src/main.ts
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
import "./styles.css";
|
||||
|
||||
const primitives = [
|
||||
{ name: "Identity", detail: "DIDs, OAuth accounts, profiles, and organization membership." },
|
||||
{ name: "Coordination", detail: "Boards, posts, threads, comments, tasks, bids, and submissions." },
|
||||
{ name: "Agents", detail: "Agent profiles, capabilities, runs, logs, permissions, and audit trails." },
|
||||
{ name: "Value", detail: "Payments, escrow, wallets, reputation events, and settlement hooks." },
|
||||
{ name: "Events", detail: "Event streams, webhooks, schema versions, and integration audit logs." }
|
||||
];
|
||||
|
||||
const schemas = [
|
||||
{ name: "logicsrc-task", path: "packages/schemas/schemas/logicsrc-task.schema.json" },
|
||||
{ name: "logicsrc-agent", path: "packages/schemas/schemas/logicsrc-agent.schema.json" },
|
||||
{ name: "logicsrc-run", path: "packages/schemas/schemas/logicsrc-run.schema.json" },
|
||||
{ name: "logicsrc-event", path: "packages/schemas/schemas/logicsrc-event.schema.json" },
|
||||
{ name: "logicsrc-plugin", path: "packages/schemas/schemas/logicsrc-plugin.schema.json" }
|
||||
];
|
||||
|
||||
const implementations = [
|
||||
{ name: "CommandBoard.run", detail: "Hosted reference product implementing the LogicSRC primitives." },
|
||||
{ name: "CLI and TUI", detail: "`commandboard` and `cb` clients for standards-compatible workflows." },
|
||||
{ name: "Reference API", detail: "Sample REST API available under `/api/*` for contract testing." },
|
||||
{ name: "Plugins", detail: "CoinPay, uGig, and sh1pt adapters prove the plugin manifest shape." }
|
||||
];
|
||||
|
||||
document.querySelector<HTMLDivElement>("#app")!.innerHTML = `
|
||||
<main class="shell">
|
||||
<aside class="rail">
|
||||
<div class="brand">
|
||||
<span class="mark">LS</span>
|
||||
<div>
|
||||
<strong>LogicSRC</strong>
|
||||
<small>Open coordination standards</small>
|
||||
</div>
|
||||
</div>
|
||||
<nav aria-label="LogicSRC sections">
|
||||
<a class="active" href="#overview">Overview</a>
|
||||
<a href="#schemas">Schemas</a>
|
||||
<a href="#cli">CLI</a>
|
||||
<a href="#reference">Reference</a>
|
||||
</nav>
|
||||
</aside>
|
||||
<section class="workspace">
|
||||
<header id="overview" class="hero">
|
||||
<div>
|
||||
<p class="eyebrow">Profullstack open spec project</p>
|
||||
<h1>LogicSRC</h1>
|
||||
<p class="lede">Open schemas, primitives, and conventions for coordination between humans, AI agents, plugins, payment systems, and hosted products.</p>
|
||||
</div>
|
||||
<div class="status-grid" aria-label="Project status">
|
||||
<span><strong>0.1</strong>draft spec</span>
|
||||
<span><strong>5</strong>schemas</span>
|
||||
<span><strong>3</strong>reference plugins</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="band">
|
||||
<div class="section-head">
|
||||
<h2>Standards Surface</h2>
|
||||
<p>LogicSRC defines the shared language; products can implement it without owning the standard.</p>
|
||||
</div>
|
||||
<div class="primitive-grid">
|
||||
${primitives.map((item) => `
|
||||
<article class="tile">
|
||||
<h3>${item.name}</h3>
|
||||
<p>${item.detail}</p>
|
||||
</article>
|
||||
`).join("")}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="schemas" class="band two-col">
|
||||
<div>
|
||||
<div class="section-head">
|
||||
<h2>Open Schemas</h2>
|
||||
<p>Versioned JSON Schema files are the contract source for tasks, agents, runs, events, and plugins.</p>
|
||||
</div>
|
||||
<div class="schema-list">
|
||||
${schemas.map((schema) => `
|
||||
<article>
|
||||
<strong>${schema.name}</strong>
|
||||
<code>${schema.path}</code>
|
||||
</article>
|
||||
`).join("")}
|
||||
</div>
|
||||
</div>
|
||||
<div id="cli" class="cli-panel">
|
||||
<h2>CLI Validation</h2>
|
||||
<pre><code>npm install
|
||||
npm run schemas:validate
|
||||
npm --workspace @logicsrc/cli run dev -- task validate ./task.yaml</code></pre>
|
||||
<p>The CLI belongs here as standards tooling: validate schemas, inspect objects, and exercise compatible implementations.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="reference" class="band">
|
||||
<div class="section-head">
|
||||
<h2>Reference Implementations</h2>
|
||||
<p>These prove the standard, but they are not the LogicSRC identity.</p>
|
||||
</div>
|
||||
<div class="implementation-list">
|
||||
${implementations.map((item) => `
|
||||
<article>
|
||||
<span></span>
|
||||
<div>
|
||||
<h3>${item.name}</h3>
|
||||
<p>${item.detail}</p>
|
||||
</div>
|
||||
</article>
|
||||
`).join("")}
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
`;
|
||||
|
||||
if ("serviceWorker" in navigator) {
|
||||
window.addEventListener("load", () => {
|
||||
navigator.serviceWorker.register("/service-worker.js").catch(() => undefined);
|
||||
});
|
||||
}
|
||||
315
apps/logicsrc-web/src/styles.css
Normal file
315
apps/logicsrc-web/src/styles.css
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
:root {
|
||||
color: #101418;
|
||||
background: #f6f7f4;
|
||||
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
font-size: 16px;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.shell {
|
||||
display: grid;
|
||||
grid-template-columns: 16rem minmax(0, 1fr);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.rail {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
padding: 1rem;
|
||||
border-right: 1px solid #d9ded4;
|
||||
background: #101418;
|
||||
color: #f6f7f4;
|
||||
}
|
||||
|
||||
.brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.brand small {
|
||||
display: block;
|
||||
margin-top: 0.15rem;
|
||||
color: #b5beb2;
|
||||
}
|
||||
|
||||
.mark {
|
||||
display: grid;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
place-items: center;
|
||||
border: 1px solid #5ac8a6;
|
||||
border-radius: 6px;
|
||||
color: #5ac8a6;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
nav a {
|
||||
min-height: 2.35rem;
|
||||
padding: 0.55rem 0.75rem;
|
||||
border: 1px solid #263039;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
nav a.active,
|
||||
nav a:hover {
|
||||
border-color: #3f5049;
|
||||
background: #1b2329;
|
||||
}
|
||||
|
||||
.workspace {
|
||||
padding: 1.25rem;
|
||||
}
|
||||
|
||||
.hero,
|
||||
.band {
|
||||
width: 100%;
|
||||
max-width: 72rem;
|
||||
margin: 0 auto 1rem;
|
||||
}
|
||||
|
||||
.hero {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(16rem, 22rem);
|
||||
gap: 1rem;
|
||||
align-items: end;
|
||||
padding: 1.25rem 0 0.25rem;
|
||||
}
|
||||
|
||||
.eyebrow,
|
||||
.section-head p,
|
||||
.tile p,
|
||||
.implementation-list p,
|
||||
.cli-panel p {
|
||||
color: #58615b;
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
margin: 0 0 0.4rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 0.45rem;
|
||||
font-size: 3rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.lede {
|
||||
max-width: 52rem;
|
||||
margin-bottom: 0;
|
||||
font-size: 1.12rem;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.status-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.status-grid span {
|
||||
min-height: 5rem;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #d6ddd2;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
color: #58615b;
|
||||
}
|
||||
|
||||
.status-grid strong {
|
||||
display: block;
|
||||
color: #101418;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.band {
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
.section-head {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.section-head h2,
|
||||
.cli-panel h2 {
|
||||
margin-bottom: 0;
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
.section-head p {
|
||||
max-width: 34rem;
|
||||
margin-bottom: 0;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.primitive-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.tile,
|
||||
.schema-list article,
|
||||
.cli-panel,
|
||||
.implementation-list article {
|
||||
border: 1px solid #d6ddd2;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tile {
|
||||
min-height: 10rem;
|
||||
padding: 0.85rem;
|
||||
}
|
||||
|
||||
.tile h3,
|
||||
.implementation-list h3 {
|
||||
margin-bottom: 0.35rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.tile p,
|
||||
.implementation-list p,
|
||||
.cli-panel p {
|
||||
margin-bottom: 0;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.two-col {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.1fr) minmax(20rem, 0.9fr);
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.schema-list {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.schema-list article {
|
||||
display: grid;
|
||||
gap: 0.35rem;
|
||||
min-height: 4.2rem;
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
code {
|
||||
overflow-wrap: anywhere;
|
||||
color: #2d6f60;
|
||||
}
|
||||
|
||||
.cli-panel {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow-x: auto;
|
||||
margin: 0.75rem 0;
|
||||
padding: 0.85rem;
|
||||
border-radius: 6px;
|
||||
background: #101418;
|
||||
color: #f6f7f4;
|
||||
}
|
||||
|
||||
.implementation-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.implementation-list article {
|
||||
display: grid;
|
||||
grid-template-columns: 0.7rem 1fr;
|
||||
gap: 0.65rem;
|
||||
min-height: 9rem;
|
||||
padding: 0.85rem;
|
||||
}
|
||||
|
||||
.implementation-list span {
|
||||
width: 0.7rem;
|
||||
height: 0.7rem;
|
||||
margin-top: 0.25rem;
|
||||
border-radius: 999px;
|
||||
background: #f0c56a;
|
||||
}
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.primitive-grid,
|
||||
.implementation-list {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.hero,
|
||||
.two-col {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.shell {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.rail {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
nav {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
nav a {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.workspace {
|
||||
padding: 0.9rem;
|
||||
}
|
||||
|
||||
.section-head,
|
||||
.hero {
|
||||
align-items: start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.status-grid,
|
||||
.primitive-grid,
|
||||
.implementation-list {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.4rem;
|
||||
}
|
||||
}
|
||||
1154
package-lock.json
generated
1154
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -12,8 +12,8 @@
|
|||
"apps/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "npm --workspace @logicsrc/schemas run build && npm --workspace @logicsrc/validators run build && npm --workspace @logicsrc/plugin-core run build && npm --workspace @logicsrc/plugin-coinpay run build && npm --workspace @logicsrc/plugin-ugig run build && npm --workspace @logicsrc/plugin-sh1pt run build && npm --workspace @logicsrc/tui run build && npm --workspace @logicsrc/cli run build && npm --workspace @logicsrc/commandboard-api run build && npm --workspace @logicsrc/commandboard-web run build",
|
||||
"start": "npm --workspace @logicsrc/commandboard-api run start",
|
||||
"build": "npm --workspace @logicsrc/schemas run build && npm --workspace @logicsrc/validators run build && npm --workspace @logicsrc/plugin-core run build && npm --workspace @logicsrc/plugin-coinpay run build && npm --workspace @logicsrc/plugin-ugig run build && npm --workspace @logicsrc/plugin-sh1pt run build && npm --workspace @logicsrc/tui run build && npm --workspace @logicsrc/cli run build && npm --workspace @profullstack/logicsrc-mcp run build && npm --workspace @logicsrc/commandboard-api run build && npm --workspace @logicsrc/commandboard-web run build && npm --workspace @logicsrc/web run build",
|
||||
"start": "npm --workspace @logicsrc/web run start",
|
||||
"test": "npm run test --workspaces --if-present",
|
||||
"check": "npm run build && npm run test",
|
||||
"schemas:validate": "npm --workspace @logicsrc/validators run validate:fixtures",
|
||||
|
|
|
|||
23
packages/logicsrc-mcp/package.json
Normal file
23
packages/logicsrc-mcp/package.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "@profullstack/logicsrc-mcp",
|
||||
"version": "0.1.0",
|
||||
"description": "MCP server for LogicSRC standards, schemas, prompts, and validators.",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"bin": {
|
||||
"logicsrc-mcp": "./dist/index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"test": "vitest run src"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logicsrc/validators": "file:../validators",
|
||||
"@modelcontextprotocol/sdk": "^1.29.0",
|
||||
"zod": "^4.1.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vitest": "^4.0.8"
|
||||
}
|
||||
}
|
||||
12
packages/logicsrc-mcp/src/index.ts
Normal file
12
packages/logicsrc-mcp/src/index.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env node
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import { createLogicSrcMcpServer } from "./server.js";
|
||||
|
||||
export { createLogicSrcMcpServer } from "./server.js";
|
||||
|
||||
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
||||
const server = createLogicSrcMcpServer();
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
}
|
||||
52
packages/logicsrc-mcp/src/server.test.ts
Normal file
52
packages/logicsrc-mcp/src/server.test.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
||||
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
||||
import { createLogicSrcMcpServer } from "./server.js";
|
||||
|
||||
describe("LogicSRC MCP server", () => {
|
||||
it("exposes schemas, validation, and prompts over MCP", async () => {
|
||||
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
||||
const server = createLogicSrcMcpServer();
|
||||
const client = new Client({ name: "test-client", version: "0.1.0" });
|
||||
|
||||
await server.connect(serverTransport);
|
||||
await client.connect(clientTransport);
|
||||
|
||||
const resources = await client.listResources();
|
||||
expect(resources.resources.some((resource) => resource.uri === "logicsrc://schemas/task")).toBe(true);
|
||||
|
||||
const schema = await client.readResource({ uri: "logicsrc://schemas/task" });
|
||||
expect(textContent(schema.contents[0])).toContain("logicsrc.task");
|
||||
|
||||
const example = await client.callTool({ name: "example_document", arguments: { kind: "task" } });
|
||||
const text = firstToolText(example);
|
||||
expect(text).toContain("Test checkout flow");
|
||||
|
||||
const validation = await client.callTool({ name: "validate_document", arguments: { kind: "task", document: text, fileName: "task.json" } });
|
||||
const validationText = firstToolText(validation);
|
||||
expect(validationText).toContain('"ok": true');
|
||||
|
||||
const prompts = await client.listPrompts();
|
||||
expect(prompts.prompts.map((prompt) => prompt.name)).toContain("create-valid-task");
|
||||
|
||||
await client.close();
|
||||
await server.close();
|
||||
});
|
||||
});
|
||||
|
||||
function textContent(content: unknown) {
|
||||
return isRecord(content) && typeof content.text === "string" ? content.text : "";
|
||||
}
|
||||
|
||||
function firstToolText(result: unknown) {
|
||||
if (!isRecord(result) || !Array.isArray(result.content)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const [first] = result.content;
|
||||
return isRecord(first) && first.type === "text" && typeof first.text === "string" ? first.text : "";
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null;
|
||||
}
|
||||
220
packages/logicsrc-mcp/src/server.ts
Normal file
220
packages/logicsrc-mcp/src/server.ts
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { z } from "zod";
|
||||
import { assertSchemaKind, parseDocument, schemas, validate, type SchemaKind } from "@logicsrc/validators";
|
||||
|
||||
const docs = {
|
||||
positioning: `LogicSRC is an open standards initiative for human and AI agent coordination, maintained by Profullstack, Inc.
|
||||
|
||||
CommandBoard.run is a hosted product by Profullstack, Inc., built on LogicSRC. LogicSRC defines identity, boards, posts, tasks, bounties, agents, agent runs, permissions, payments, escrow, reputation, events, webhooks, CLI commands, API schemas, and plugin contracts.`,
|
||||
roadmap: `LogicSRC v1.0 focuses on schemas, validation tooling, plugin manifests, CLI/TUI conventions, event streams, agent profiles, permissions, and reference implementations.`,
|
||||
primitives: `Core LogicSRC primitives: users, DIDs, OAuth accounts, profiles, organizations, boards, posts, threads, comments, tasks, bids, submissions, agents, agent runs, payments, escrows, wallets, reputation events, files, API keys, permissions, audit logs, webhooks, schema versions, and plugin audit logs.`
|
||||
} as const;
|
||||
|
||||
const schemaKinds = Object.keys(schemas) as SchemaKind[];
|
||||
|
||||
export function createLogicSrcMcpServer() {
|
||||
const server = new McpServer(
|
||||
{
|
||||
name: "@profullstack/logicsrc-mcp",
|
||||
version: "0.1.0"
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
resources: {},
|
||||
tools: {},
|
||||
prompts: {}
|
||||
},
|
||||
instructions: "Use this server for LogicSRC standards, schema resources, validation, and draft object generation. Treat CommandBoard.run as a reference implementation, not the standards identity."
|
||||
}
|
||||
);
|
||||
|
||||
for (const [name, text] of Object.entries(docs)) {
|
||||
const uri = `logicsrc://docs/${name}`;
|
||||
server.registerResource(
|
||||
`logicsrc-${name}`,
|
||||
uri,
|
||||
{
|
||||
title: `LogicSRC ${titleCase(name)}`,
|
||||
description: `LogicSRC ${name} reference text.`,
|
||||
mimeType: "text/markdown"
|
||||
},
|
||||
async () => ({ contents: [{ uri, mimeType: "text/markdown", text }] })
|
||||
);
|
||||
}
|
||||
|
||||
for (const kind of schemaKinds) {
|
||||
const uri = `logicsrc://schemas/${kind}`;
|
||||
server.registerResource(
|
||||
`logicsrc-schema-${kind}`,
|
||||
uri,
|
||||
{
|
||||
title: `LogicSRC ${kind} schema`,
|
||||
description: `JSON Schema for LogicSRC ${kind} documents.`,
|
||||
mimeType: "application/schema+json"
|
||||
},
|
||||
async () => ({
|
||||
contents: [
|
||||
{
|
||||
uri,
|
||||
mimeType: "application/schema+json",
|
||||
text: JSON.stringify(schemas[kind], null, 2)
|
||||
}
|
||||
]
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
server.registerTool(
|
||||
"list_schema_kinds",
|
||||
{
|
||||
title: "List LogicSRC Schema Kinds",
|
||||
description: "Lists the LogicSRC schema kinds exposed by this standards server.",
|
||||
annotations: { readOnlyHint: true, openWorldHint: false }
|
||||
},
|
||||
async () => textResult(JSON.stringify({ schemaKinds }, null, 2))
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
"validate_document",
|
||||
{
|
||||
title: "Validate LogicSRC Document",
|
||||
description: "Validates a JSON or YAML document against a LogicSRC schema kind.",
|
||||
inputSchema: {
|
||||
kind: z.enum(["agent", "event", "plugin", "run", "task"]),
|
||||
document: z.string().describe("JSON or YAML document text."),
|
||||
fileName: z.string().optional().describe("Optional file name used to select JSON parsing when it ends with .json.")
|
||||
},
|
||||
annotations: { readOnlyHint: true, openWorldHint: false }
|
||||
},
|
||||
async ({ kind, document, fileName }) => {
|
||||
const parsed = parseDocument(document, fileName ?? "document.yaml");
|
||||
const result = validate(assertSchemaKind(kind), parsed);
|
||||
return textResult(JSON.stringify(result.ok ? { ok: true, kind: result.kind } : { ok: false, kind: result.kind, errors: result.errors }, null, 2));
|
||||
}
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
"example_document",
|
||||
{
|
||||
title: "Generate Example LogicSRC Document",
|
||||
description: "Returns a minimal example document for a LogicSRC schema kind.",
|
||||
inputSchema: {
|
||||
kind: z.enum(["agent", "event", "plugin", "run", "task"])
|
||||
},
|
||||
annotations: { readOnlyHint: true, openWorldHint: false }
|
||||
},
|
||||
async ({ kind }) => textResult(JSON.stringify(exampleFor(kind), null, 2))
|
||||
);
|
||||
|
||||
server.registerPrompt(
|
||||
"create-valid-task",
|
||||
{
|
||||
title: "Create Valid LogicSRC Task",
|
||||
description: "Prompt template for turning a workflow request into a valid LogicSRC task.",
|
||||
argsSchema: {
|
||||
request: z.string().describe("Human description of the desired task.")
|
||||
}
|
||||
},
|
||||
async ({ request }) => ({
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: {
|
||||
type: "text",
|
||||
text: `Create a valid LogicSRC task JSON document for this request. Use logicsrc://schemas/task and keep it minimal unless details are required.\n\nRequest:\n${request}`
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
);
|
||||
|
||||
server.registerPrompt(
|
||||
"review-plugin-manifest",
|
||||
{
|
||||
title: "Review LogicSRC Plugin Manifest",
|
||||
description: "Prompt template for reviewing a plugin manifest against the LogicSRC plugin schema.",
|
||||
argsSchema: {
|
||||
manifest: z.string().describe("Plugin manifest JSON or YAML.")
|
||||
}
|
||||
},
|
||||
async ({ manifest }) => ({
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: {
|
||||
type: "text",
|
||||
text: `Review this LogicSRC plugin manifest against logicsrc://schemas/plugin. Identify schema issues, security concerns, missing permissions, and unclear capabilities.\n\nManifest:\n${manifest}`
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
function textResult(text: string) {
|
||||
return { content: [{ type: "text" as const, text }] };
|
||||
}
|
||||
|
||||
function titleCase(value: string) {
|
||||
return value.replace(/(^|-)([a-z])/g, (_match, prefix: string, letter: string) => `${prefix ? " " : ""}${letter.toUpperCase()}`);
|
||||
}
|
||||
|
||||
function exampleFor(kind: SchemaKind) {
|
||||
switch (kind) {
|
||||
case "agent":
|
||||
return {
|
||||
type: "logicsrc.agent",
|
||||
version: "0.1",
|
||||
agent_did: "qa-agent-01.coinpay",
|
||||
name: "QA Agent",
|
||||
capabilities: ["browser.qa", "report.write"],
|
||||
status: "active"
|
||||
};
|
||||
case "event":
|
||||
return {
|
||||
type: "logicsrc.event",
|
||||
version: "0.1",
|
||||
event_id: "evt_123",
|
||||
event_type: "task.created",
|
||||
resource_type: "task",
|
||||
resource_id: "task_123",
|
||||
actor_did: "anthony.coinpay",
|
||||
created_at: new Date(0).toISOString()
|
||||
};
|
||||
case "plugin":
|
||||
return {
|
||||
type: "logicsrc.plugin",
|
||||
version: "0.1",
|
||||
id: "example-plugin",
|
||||
name: "Example Plugin",
|
||||
description: "Example LogicSRC plugin manifest.",
|
||||
capabilities: ["tasks.read"],
|
||||
permissions: ["tasks:read"]
|
||||
};
|
||||
case "run":
|
||||
return {
|
||||
type: "logicsrc.run",
|
||||
version: "0.1",
|
||||
run_id: "run_123",
|
||||
task_id: "task_123",
|
||||
agent_did: "qa-agent-01.coinpay",
|
||||
status: "completed",
|
||||
started_at: new Date(0).toISOString()
|
||||
};
|
||||
case "task":
|
||||
return {
|
||||
type: "logicsrc.task",
|
||||
version: "0.1",
|
||||
title: "Test checkout flow",
|
||||
description: "Verify checkout flow across desktop and mobile.",
|
||||
board: "/qa",
|
||||
creator_did: "anthony.coinpay",
|
||||
status: "open",
|
||||
budget: { amount: 25, currency: "USDC" },
|
||||
agent_allowed: true,
|
||||
human_allowed: true
|
||||
};
|
||||
}
|
||||
}
|
||||
8
packages/logicsrc-mcp/tsconfig.json
Normal file
8
packages/logicsrc-mcp/tsconfig.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue