Skip to main content سوق المهارات اكتشف واستكشف مهارات الذكاء الاصطناعي التي بناها المجتمع.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
نسخ Promptعرض تفاصيل Prompt يتجاوز الأمر المباشر Prompt المخصّص للمراجعة. افحص المصدر قبل تشغيله.
npx skills add https://github.com/decocms/studio --skill add-mcp-toolsيبقى الأمر في سطر واحد. مرّر أفقيًا لمراجعته كاملًا قبل النسخ.
تفضّل نسخة محلية؟ نزّل الملفات المتاحة حاليًا لدى SkillsMP.
تحميل Zip جاري التحميل... Install and self-host deco Studio (the open-source control plane) on the user's own infrastructure. Use when the user wants to install, run, self-host, or deploy Studio locally (Docker, Rancher Desktop, kind, minikube) or on Kubernetes (managed or self-managed), or asks to "install Studio", "self-host decocms", configure the Studio Helm chart, or troubleshoot a Studio install. Detects the environment, picks the right tier, configures the charts correctly, validates end-to-end, and fixes the common failure modes.
المهن ذات الصلة SOC
استنادا إلى تصنيف SOC المهني
name add-mcp-tools description Guide for adding new MCP tools with consistent patterns for schemas, tool definitions, registry updates, and Better Auth integration
Adding New MCP Tools to Studio
This guide documents the pattern for adding new MCP tools to Studio codebase. Follow this checklist to ensure consistency with existing tools.
Overview
MCP tools are exposed via the Model Context Protocol and allow programmatic management of resources. Each tool follows a consistent pattern with:
Zod schemas for input/output validation
defineTool for automatic tracing, metrics, and audit logging
Access control via ctx.access.check()
Better Auth integration via ctx.boundAuth
File Structure
When adding a new domain of tools (e.g., apiKeys, webhooks, secrets), create the following structure:
apps/api/src/tools/<domain>/
├── schema.ts # Zod schemas for entities and operations
├── create.ts # <DOMAIN>_CREATE tool
├── list.ts # <DOMAIN>_LIST tool
├── update.ts # <DOMAIN>_UPDATE tool
├── delete.ts # <DOMAIN>_DELETE tool
└── index.ts # Barrel export
Step-by-Step Checklist
1. Create Schema File (schema.ts)
Define Zod schemas for:
Entity schema : The resource returned in list/get operations
Create input/output schemas : Input for creation, output includes created entity
Update input/output schemas : Partial updates
Delete input/output schemas : ID input, success confirmation output
{ z } ;
= z. ({
: z. (),
: z. (),
: z. ([z. (), z. ()]),
});
= z. < >;
= z. ({
: z. (). ( ). ( ),
});
= z. ({
: ,
});
= z. ({
});
= z. ({
: z. ( ),
});
= z. ({
: z. (),
});
= z. ({
: ,
});
= z. ({
: z. (),
});
= z. ({
: z. (),
: z. (),
});
import
from
"zod"
export
const
MyEntitySchema
object
id
string
name
string
createdAt
union
string
date
export
type
MyEntity
infer
typeof
MyEntitySchema
export
const
MyCreateInputSchema
object
name
string
min
1
max
255
export
const
MyCreateOutputSchema
object
item
MyEntitySchema
export
const
MyListInputSchema
object
export
const
MyListOutputSchema
object
items
array
MyEntitySchema
export
const
MyUpdateInputSchema
object
id
string
export
const
MyUpdateOutputSchema
object
item
MyEntitySchema
export
const
MyDeleteInputSchema
object
id
string
export
const
MyDeleteOutputSchema
object
success
boolean
id
string
2. Create Tool Files Each tool file follows this pattern:
import { defineTool } from "../../core/define-tool" ;
import { getUserId, requireAuth, requireOrganization } from "../../core/studio-context" ;
import { MyCreateInputSchema , MyCreateOutputSchema } from "./schema" ;
export const MY_DOMAIN_CREATE = defineTool ({
name : "MY_DOMAIN_CREATE" ,
description : "Create a new resource" ,
inputSchema : MyCreateInputSchema ,
outputSchema : MyCreateOutputSchema ,
handler : async (input, ctx) => {
requireAuth (ctx);
const organization = requireOrganization (ctx);
await ctx.access .check ();
const userId = getUserId (ctx);
if (!userId) {
throw new Error ("User ID required" );
}
const result = await ctx.boundAuth .myDomain .create ({ ... });
const result = await ctx.storage .myDomain .create ({ ... });
return { item : result };
},
});
3. Create Barrel Export (index.ts)
export { MY_DOMAIN_CREATE } from "./create" ;
export { MY_DOMAIN_LIST } from "./list" ;
export { MY_DOMAIN_UPDATE } from "./update" ;
export { MY_DOMAIN_DELETE } from "./delete" ;
export * from "./schema" ;
4. Update Tool Registry (registry.ts) Add tool names and metadata:
export type ToolCategory = "Organizations" | "Connections" | "My Domain" ;
const ALL_TOOL_NAMES = [
"MY_DOMAIN_CREATE" ,
"MY_DOMAIN_LIST" ,
"MY_DOMAIN_UPDATE" ,
"MY_DOMAIN_DELETE" ,
] as const ;
export const MANAGEMENT_TOOLS : ToolMetadata [] = [
{
name : "MY_DOMAIN_CREATE" ,
description : "Create resource" ,
category : "My Domain" ,
},
{
name : "MY_DOMAIN_LIST" ,
description : "List resources" ,
category : "My Domain" ,
},
{
name : "MY_DOMAIN_UPDATE" ,
description : "Update resource" ,
category : "My Domain" ,
},
{
name : "MY_DOMAIN_DELETE" ,
description : "Delete resource" ,
category : "My Domain" ,
dangerous : true ,
},
];
const TOOL_LABELS : Record <ToolName , string > = {
MY_DOMAIN_CREATE : "Create resource" ,
MY_DOMAIN_LIST : "List resources" ,
MY_DOMAIN_UPDATE : "Update resource" ,
MY_DOMAIN_DELETE : "Delete resource" ,
};
export function getToolsByCategory ( ) {
const grouped : Record <string , ToolMetadata []> = {
Organizations : [],
Connections : [],
"My Domain" : [],
};
}
5. Register Tools (tools/index.ts)
import * as MyDomainTools from "./myDomain" ;
export { MyDomainTools };
export const ALL_TOOLS = [
MyDomainTools .MY_DOMAIN_CREATE ,
MyDomainTools .MY_DOMAIN_LIST ,
MyDomainTools .MY_DOMAIN_UPDATE ,
MyDomainTools .MY_DOMAIN_DELETE ,
] as const satisfies { name : ToolName }[];
6. Add to Default Permissions (if needed)
apiKey ({
permissions : {
defaultPermissions : {
self : [
"MY_DOMAIN_LIST" ,
],
},
},
}),
7. Add Better Auth Integration (if wrapping Better Auth API) If your tools wrap Better Auth APIs, you need to:
a. Add types to studio-context.ts:
export type MyDomainCreateResult = Awaited <
ReturnType <BetterAuthApi ["createMyDomain" ]>
>;
export interface BoundAuthClient {
myDomain : {
create (data : { ... }): Promise <MyDomainCreateResult >;
list (): Promise <MyDomainListResult >;
update (data : { ... }): Promise <MyDomainUpdateResult >;
delete (id : string ): Promise <void >;
};
}
b. Implement in context-factory.ts:
function createBoundAuthClient (ctx : AuthContext ): BoundAuthClient {
return {
myDomain : {
create : async (data) => {
return auth.api .createMyDomain ({ headers, body : data });
},
list : async () => {
return auth.api .listMyDomain ({ headers });
},
update : async (data) => {
return auth.api .updateMyDomain ({ headers, body : data });
},
delete : async (id) => {
await auth.api .deleteMyDomain ({ headers, body : { id } });
},
},
};
}
Key Patterns to Follow
Authentication & Authorization
requireAuth (ctx);
const org = requireOrganization (ctx);
await ctx.access .check ();
Error Handling
if (!result) {
throw new Error (`Resource not found: ${id} ` );
}
if (result.organizationId !== organization.id ) {
throw new Error ("Resource not found in organization" );
}
Sensitive Data For sensitive data (like API key values):
export const CreateOutputSchema = z.object ({
id : z.string (),
secretValue : z.string (),
});
export const EntitySchema = z.object ({
id : z.string (),
});
Testing Create test files alongside tool files:
apps/api/src/tools/<domain>/
├── create.test.ts
├── list.test.ts
├── update.test.ts
└── delete.test.ts
Use the existing test patterns from apps/api/src/tools/connection/ as reference.
Common Mistakes to Avoid
Forgetting await ctx.access.check() - Always check authorization
Missing tool registration - Update both registry.ts AND tools/index.ts
Inconsistent naming - Use DOMAIN_ACTION pattern (e.g., API_KEY_CREATE)
Missing default permissions - Add to auth/index.ts if users should have access by default
Exposing sensitive data - Only return secrets at creation time
Missing organization check - Use requireOrganization(ctx) for org-scoped resources