Ontology MCP 도구와 에이전트 구성
액션 도구 설명
Ontology Manager의 Agent tool description은 에이전트에게 표시되는 액션 설명입니다. 언제 사용하고 어떤 입력을 먼저 찾아야 하는지 적습니다. 예를 들어 작업 생성 액션이 연결할 프로젝트 ID를 요구한다면 그 ID를 얻는 방법을 안내합니다.
Claude 스킬로 업무 절차 구성
스킬은 여러 MCP 도구를 어떤 순서로 사용할지 재사용 지시문으로 묶습니다. 다음 get-or-create-task 예시는 프로젝트와 제목으로 기존 작업을 먼저 찾고 없을 때만 생성합니다. 실제 도구명과 매개변수는 연결한 앱에서 제공하는 스키마와 맞춰야 합니다.
---
name: get-or-create-task
description: Searches for a task by title in a project, returns it if found, or creates a new task if not found
---
# Get or create task
Find an existing task by title within a project, or create a new task if no match is found.
## Instructions
1. Search for the task by title using the search tool:
- Tool: `search-osdk-todo-task`
- Filter results by `project_id` if provided
2. Evaluate results:
- If a match is found, return the existing task details
- If multiple matches are found, use the first match
- If no matches are found, proceed to create a new task
3. Create a new task using the create task action tool:
- Tool: `create-osdk-todo-task`
- Required parameters: `title`, `project_id`
- Optional parameters: `description`, `status`, `assigned_to`, `start_date`, `due_date`
4. Return the task details including ID, title, project, status, and assignee
이 예시는 여러 결과가 있으면 첫 결과를 선택하도록 지시하므로 업무에서 중복을 처리할 기준과 일치하는지 확인합니다. 검색 후 생성은 데이터베이스의 원자적 유일성 보장을 대신하지 않습니다.
Copilot Studio 연결
Copilot Studio 연동은 confidential client의 authorization code grant를 사용합니다. Developer Console 앱을 만들 때 Backend service와 User's permissions를 선택합니다. 사용자 대신 토큰을 발행하는 이 구성과 일반 client credentials 서비스 실행을 혼동하지 않습니다.
Adaptive Cards를 사용하면 온톨로지 도구의 구조화 데이터를 Teams, Copilot, Outlook 등에 카드로 표시할 수 있습니다. Action.OpenUrlDialog는 Teams나 Copilot에서 사용자 정의 URL 대화상자를 열어 반환 데이터와 상호작용하게 합니다.
VS Code와 Adaptive Cards
VS Code에 Microsoft 365 Agents Toolkit과 Adaptive Card Previewer 확장을 설치합니다. 프로젝트 .vscode/mcp.json에 서버 연결을 구성합니다. URL은 Developer Console에서 복사하고 FOUNDRY_TOKEN은 안전하게 제공하는 환경변수입니다.
{
"inputs": [],
"servers": {
"todo-confidential": {
"type": "http",
"url": "<your-ontology-mcp-server-url>",
"headers": {
"Authorization": "Bearer ${env:FOUNDRY_TOKEN}",
"Accept": "application/json, text/event-stream"
}
}
}
}
Toolkit 패널에서 Start를 선택하고 서버에 연결한 다음 안내에 따라 adaptive agent를 만듭니다.
도구 정의의 capabilities.response_semantics에 렌더링 구성을 넣습니다. data_path는 응답 안의 데이터 JSON 경로이고 static_template.file은 카드 템플릿 파일입니다. 다음은 가상의 GetCustomerList 응답을 표시하는 예시입니다.
{
"name": "GetCustomerList",
"description": "List all customers.\n\n Returns:\n A list of CustomerSummary objects with key customer properties.",
"parameters": {
"type": "object",
"properties": {},
"required": []
},
"capabilities": {
"response_semantics": {
"data_path": "$",
"static_template": {
"file": "adaptiveCards/customerList.json"
}
}
}
}
카드 생성 스킬 예시
Claude Code에 서버를 연결하고 프로젝트의 .claude/skills/build-adaptive-card/ 디렉터리를 만든 뒤 아래 내용을 SKILL.md로 저장합니다. 전체 경로는 .claude/skills/build-adaptive-card/SKILL.md입니다. 대상 도구를 확인하고 실제 응답 형태, nullable 필드와 숫자 형식을 조사하여 카드 및 미리보기 데이터를 생성하는 절차입니다. 도구를 실행하여 표본을 얻는 단계가 있으므로 호출 대상과 입력이 허용된 범위인지 확인합니다.
응답이 JSON을 다시 문자열로 인코딩한 형태면 템플릿이 직접 바인딩할 수 없으므로 서버가 네이티브 객체나 배열을 반환하게 수정합니다. 단일 객체, 루트 배열, value 배열의 형태에 맞춰 바인딩을 선택합니다. 아래 스킬은 카드 1.5, 줄바꿈, null 보호, 숫자 표시 및 조건부 색상을 사용하고 .length 등을 쓰지 않는 제한된 작성 규칙을 정의합니다.
---
name: build-adaptive-card
description: Build an Adaptive Card for a specific MCP tool connected to Claude Code
---
# Build Adaptive Card for MCP Tool
You are helping the user build an Adaptive Card for a specific MCP tool that is connected
to Claude Code in this session.
## Instructions
Follow these steps precisely:
### Step 1: Identify the target tool
Ask the user which MCP tool they want to build an Adaptive Card for. List the available
MCP tools you know about from the connected MCP server. If the user has already named the
tool, skip asking.
### Step 2: Call the tool to get a real response sample
Call the named MCP tool with minimal or sample arguments to get a real response. If the
tool requires arguments, use the most minimal and representative ones possible. Capture the
full JSON response.
If the tool requires arguments you cannot guess, ask the user for sample argument values
before calling.
### Step 3: Validate the response shape
Inspect each property of the returned object. If any property value is a string that is
itself valid JSON (starts with `[` or `{` and parses as JSON), the tool is double-serializing
its output. Stop and tell the user:
> The tool is returning its data as a JSON-encoded string instead of a native JSON
> object or array. Adaptive Card templates cannot bind to a string. Fix the MCP server
> tool implementation to return a native Python dict or list instead of `json.dumps(...)`.
Do not proceed until the user confirms the tool has been fixed.
If the response is valid JSON, determine:
- Is the top-level response an object with a `value` array? (MCP envelope pattern)
- Or is it a flat array or a single object?
- What are the field names, types, and which fields are nullable?
- Which fields are numeric and might benefit from formatting (currency, percentages)?
### Step 4: Generate the Adaptive Card JSON
Create an Adaptive Card (version 1.5) following these rules:
**Template binding:**
- If response is `{"value": [...]}`, use `"$data": "${value}"` on the repeating Container
- If response is a flat array, use `"$data": "${$root}"` on the repeating Container
- If response is a single object, bind fields directly with `${fieldName}`
**Card structure:**
- Start with a header Container (`style: "emphasis"`, `bleed: true`) with a title TextBlock
- For list responses: use a repeating Container with a ColumnSet inside
- For single-object responses: use a FactSet or labeled rows
- Use `"wrap": true` on all TextBlocks
- For nullable fields, add `"$when": "${field != null}"` guards
- For currency fields: use `formatNumber` for display formatting
- For status color coding: use conditional `if()` expressions
- Do NOT use `.length` on arrays (not supported in template language)
- Do NOT use date functions, structs, arrays, or window functions
**File naming:** `appPackage/adaptiveCards/<toolName>.json` (camelCase the tool name)
Write the card JSON to `appPackage/adaptiveCards/<toolName>.json`.
Next, write a companion `.data.json` file at `appPackage/adaptiveCards/<toolName>.data.json`
containing the actual sample response for design-time preview data.
### Step 5: Wire up response_semantics in ai-plugin.json
Read `appPackage/ai-plugin.json`. Find the function entry matching the tool name. Add or
update the `capabilities` block:
```json
"capabilities": {
"response_semantics": {
"data_path": "$",
"static_template": {
"file": "adaptiveCards/<toolName>.json"
}
}
}
```
### Step 6: Report to the user
Print a summary of the card file created, the data sample file created, the function updated
in `ai-plugin.json`, the `data_path` used, and key design decisions made.
## Key constraints
- `response_semantics` must be inside `capabilities`, not directly on the function
- `static_template` uses `"file": "adaptiveCards/foo.json"` (the toolkit inlines at build time)
- Adaptive Card template language does not support `.length`
- `$schema` for the card: `"http://adaptivecards.io/schemas/adaptive-card.json"`
- Card version: `"1.5"`
Build a card for the GetCustomerList tool처럼 요청하면 지정 도구의 카드, .data.json 표본과 ai-plugin.json의 연결을 만들도록 지시합니다. response_semantics는 함수 루트가 아니라 capabilities 안에 있어야 하며 Toolkit이 빌드 시 static_template.file의 내용을 포함합니다.