Token导航 LogoToken导航TokenDH.com
前端设计external-servicegithub未标认证来源可访问许可证需确认审计通过

implementing-mcp-ui-appsimplementing MCP UI apps 浏览器

Agent Skill

用于辅助界面设计、视觉规范、排版、配色、布局和交互体验优化。它适合让 Agent 根据产品场景整理页面结构、生成 UI 方案、检查视觉一致性或改进组件层级。使用时需要结合现有品牌、设计系统和用户任务,不应只堆装饰元素;涉及真实页面改动时,应通过截图或浏览器预览检查文本溢出、对齐和响应式表现。

总安装

367

周安装

15

GitHub Stars

34,184

下载量

119
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:implementing-mcp-ui-apps(implementing MCP UI apps 浏览器)
来源仓库:https://github.com/posthog/posthog
仓库路径:skills/implementing-mcp-ui-apps
安装命令:
npx skills add https://github.com/posthog/posthog --skill implementing-mcp-ui-apps
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/posthog/posthog --skill implementing-mcp-ui-apps

简介

用于辅助界面设计、视觉规范和交互体验优化。

  • 适用于 Codex、Claude、Cursor 和 Gemini CLI 中的前端开发任务。
  • 通过 GitHub 仓库安装,需结合 React 和 Tailwind 技术栈。
  • 生成 UI 时应通过浏览器预览检查响应式和可访问性。
  • implementing-mcp-ui-apps 属于前端设计类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Implementing MCP UI apps

MCP UI apps are interactive React visualizations that render alongside tool results in MCP clients (e.g. Claude Desktop). They're built with the Mosaic component library and served via Cloudflare Workers Static Assets.

Full reference: services/mcp/CONTRIBUTING.md.

Quick workflow

# 1. Create view components in your product's mcp/apps/ directory
#    (see "View components" below)

# 2. Add ui_apps entries to your product's mcp/tools.yaml
#    (see "YAML configuration" below)

# 3. Link tools to apps with ui_app: <key> in the tools section

# 4. Generate entry points + registry, then build
pnpm --filter=@posthog/mcp run generate:ui-apps
pnpm --filter=@posthog/mcp run build

When to add a UI app

When an MCP tool returns structured data that benefits from visual presentation — tables, detail views, charts, status badges, etc. Without a UI app, tool results are shown as plain text/JSON in the chat.

Architecture

products/{product}/mcp/
  apps/                          # React view components (you write these)
    EntityView.tsx               # Detail view
    EntityListView.tsx           # List view (uses ListDetailView from Mosaic)
    index.ts                     # Barrel exports
  tools.yaml                     # YAML config: ui_apps + tools

services/mcp/
  src/ui-apps/apps/
    generated/                   # Auto-generated entry points (don't edit)
    debug.tsx                    # Custom/manual entry points
    query-results.tsx
  src/resources/
    ui-apps.generated.ts         # Auto-generated: URI constants, UiAppKey, URI_MAP, UI_APPS
    ui-apps.ts                   # Hand-authored: withUiApp(), registerUiAppResources()
  scripts/
    generate-ui-apps.ts          # The generator — reads YAML, writes entry points + registry
    yaml-config-schema.ts        # Zod schemas for YAML validation (source of truth for field definitions)

View components

Place view components in products/{product}/mcp/apps/.

Detail view — renders a single entity:

import { type ReactElement } from 'react'
import { Card, DescriptionList, Stack } from '@posthog/mosaic'

export interface MyEntityData {
  id: number
  name: string
  // ... fields from the API response
}

export function MyEntityView({ data }: { data: MyEntityData }): ReactElement {
  return (
    <Card title={data.name}>
      <DescriptionList items={[{ label: 'ID', value: String(data.id) }]} />
    </Card>
  )
}

List view — uses ListDetailView from Mosaic for the list-to-detail state machine:

import { type ReactElement, type ReactNode } from 'react'
import { DataTable, type DataTableColumn, ListDetailView, Stack } from '@posthog/mosaic'
import { MyEntityView, type MyEntityData } from './MyEntityView'

export interface MyEntityListData {
  results: MyEntityData[]
  _posthogUrl?: string
}

export interface MyEntityListViewProps {
  data: MyEntityListData
  onMyEntityClick?: (entity: MyEntityData) => Promise<MyEntityData | null>
}

export function MyEntityListView({ data, onMyEntityClick }: MyEntityListViewProps): ReactElement {
  return (
    <ListDetailView<MyEntityData>
      onItemClick={onMyEntityClick}
      backLabel="All entities"
      getItemName={(e) => e.name}
      renderDetail={(e) => <MyEntityView data={e} />}
      renderList={(handleClick) => {
        const columns: DataTableColumn<MyEntityData>[] = [
          {
            key: 'name',
            header: 'Name',
            sortable: true,
            render: (row): ReactNode =>
              onMyEntityClick ? (
                <button onClick={() => handleClick(row)} className="text-link underline ...">
                  {row.name}
                </button>
              ) : (
                row.name
              ),
          },
        ]
        return (
          <div className="p-4">
            <Stack gap="sm">
              <DataTable columns={columns} data={data.results} pageSize={10} />
            </Stack>
          </div>
        )
      }}
    />
  )
}

Barrel export (index.ts):

export { MyEntityView, type MyEntityData } from './MyEntityView'
export { MyEntityListView, type MyEntityListData, type MyEntityListViewProps } from './MyEntityListView'

YAML configuration

The ui_apps section in products/{product}/mcp/tools.yaml defines UI apps. Each key becomes the app identifier (used in URIs, constants, and withUiApp calls).

There are three app types: detail, list, and custom.

type: detail — single-entity view

Renders one entity using a view component wrapped in AppWrapper.

Required fields:

FieldDescription
typeMust be 'detail'.
view_propThe React prop name passed to the view component (e.g. data, action, flag). Cannot be derived — must match your component's props.

Optional fields (derived by convention when omitted):

FieldDefaultDescription
app_name"PostHog " + titleCase(key)Display name shown in the MCP client. Example: key error-details"PostHog Error Details".
descriptiontitleCase(key) + " detail view"Short description for the MCP resource registry.
component_importproducts/{product}/mcp/appsImport path for the view component. Auto-derived from the YAML file's location in the product directory.
data_typePascalCase(key) + "Data"TypeScript type for the tool result. Example: key error-detailsErrorDetailsData.
view_componentPascalCase(key) + "View"React component name. Example: key error-detailsErrorDetailsView.

Minimal example:

ui_apps:
  action:
    type: detail
    view_prop: action

Example with overrides (when conventions don't match the actual code):

ui_apps:
  llm-costs:
    type: detail
    view_prop: data
    data_type: LLMCostsData # convention would produce LlmCostsData
    view_component: LLMCostsView # convention would produce LlmCostsView

type: list — list with drill-down

Renders a list component. When an item is clicked, calls a detail tool via app.callServerTool() and shows the detail view inline. Falls back to a chat message if the MCP client doesn't support tool calls from apps.

Required fields:

FieldDescription
typeMust be 'list'.
detail_toolTool name to call when a list item is clicked (e.g. 'action-get', 'cohorts-retrieve'). Must be a valid tool name defined in the tools section of any YAML file.

Optional fields with behavioral defaults:

FieldDefaultDescription
detail_args'{id: item.id}'JS expression for arguments passed to detail_tool. The variable item refers to the clicked list item. Override when the tool uses a different param name, e.g. '{flagId: item.id}'.
item_name_field'name'Field on the item object used for display in loading states and fallback chat messages. Override when items are identified by something other than name, e.g. key for feature flags.
click_prop'on' + PascalCase(singularKey) + 'Click'Prop name for the click handler passed to the list component. The singular key is derived by stripping the -list suffix. Example: key action-listonActionClick. Override when your component uses a shorter name, e.g. onFlagClick instead of onFeatureFlagClick.
entity_labelkebab-to-space of singular keyHuman-readable label used in the fallback chat message ("Show me the details for {entity_label}..."). Example: key error-issue-listerror issue.

Optional fields with convention defaults (same pattern as detail apps):

FieldDefaultDescription
app_name"PostHog " + titleCase(key)Display name.
descriptiontitleCase(key) + " view"Short description.
component_importproducts/{product}/mcp/appsImport path.
list_data_typePascalCase(singularKey) + "ListData"TypeScript type for the list response. Example: key action-listActionListData.
item_data_typePascalCase(singularKey) + "Data"TypeScript type for a single item. Example: key action-listActionData.
view_componentPascalCase(key) + "View"React component name. Example: key action-listActionListView.

Minimal example:

ui_apps:
  action-list:
    type: list
    detail_tool: action-get

Example with overrides:

ui_apps:
  feature-flag-list:
    type: list
    detail_tool: feature-flag-get-definition
    detail_args: '{ flagId: item.id }' # tool expects flagId, not id
    item_name_field: key # flags are identified by key, not name
    click_prop: onFlagClick # component uses onFlagClick, not onFeatureFlagClick

type: custom — handwritten entry point

For apps that need fully custom logic (e.g. debug.tsx, query-results.tsx). The generator does NOT create an entry point — you maintain it manually at services/mcp/src/ui-apps/apps/{key}.tsx. Only the registry entry is generated.

Required fields:

FieldDescription
typeMust be 'custom'.
app_nameDisplay name. Required because there's no convention to derive it from (custom apps may not follow naming patterns).
descriptionShort description. Required for the same reason.

Example:

ui_apps:
  query-results:
    type: custom
    app_name: Query Results
    description: Interactive visualization for PostHog query results

Where the schemas live

The Zod schemas that validate these YAML fields live in services/mcp/scripts/yaml-config-schema.ts. Each field has a JSDoc comment explaining its purpose and default.

To add a new field to an app type:

  1. Add it to the relevant Zod schema (DetailUiAppSchema, ListUiAppSchema, or CustomUiAppSchema) with .optional() if it has a default
  2. Add it to the matching Resolved* interface (ResolvedDetailUiApp or ResolvedListUiApp)
  3. Add the default derivation in resolveDetailApp() or resolveListApp() in generate-ui-apps.ts
  4. Use the resolved value in generateDetailApp() or generateListApp()

All schemas use .strict() — unknown keys are rejected at build time, catching typos.

Linking tools to UI apps

In the tools section of the same YAML file, use ui_app to reference a ui_apps key:

tools:
  my-entity-get:
    operation: my_entities_retrieve
    enabled: true
    ui_app: my-entity # references ui_apps.my-entity
  my-entity-list:
    operation: my_entities_list
    enabled: true
    ui_app: my-entity-list # references ui_apps.my-entity-list

The generator validates that every ui_app value points to a key that exists in some ui_apps section across all YAML files.

For handwritten tools (not YAML-generated), use withUiApp in TypeScript:

import { withUiApp } from '@/resources/ui-apps'
import { withPostHogUrl, type WithPostHogUrl } from '@/tools/tool-utils'
import type { Context, ToolBase } from '@/tools/types'

type Result = WithPostHogUrl<MyEntityData>

export default (): ToolBase<typeof schema, Result> =>
  withUiApp('my-entity', {
    name: 'my-entity-get',
    schema,
    handler: async (context, params) => {
      const projectId = await context.stateManager.getProjectId()
      const data = await fetchEntity(context, params)
      return await withPostHogUrl(context, data, `/my-entities/${data.id}`)
    },
  })

The appKey parameter is type-checked against the generated UiAppKey union — invalid keys are compile-time errors.

CI validation

CI checks that generated files are up to date in both ci-mcp.yml and ci-mcp-ui-apps.yml. If you change YAML ui_apps sections, run pnpm --filter=@posthog/mcp run generate:ui-apps and commit the result.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

37.37%
按下载量换算44

Claude

31.49%
按下载量换算37

Cursor

18.12%
按下载量换算22

Gemini CLI

9.07%
按下载量换算11

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

external-service

该 Skill 可能调用第三方服务、云服务或外部模型 API,使用前需要确认账号、额度、数据发送范围和服务条款。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills