新的 gsap 片头入场动画

This commit is contained in:
锦恢 2025-06-05 22:43:11 +08:00
parent 644d537ec3
commit b6c81342a9
15 changed files with 682 additions and 349 deletions

View File

@ -63,7 +63,7 @@ export default withMermaid({
},
head: [
['link', { rel: 'icon', href: baseUrl + '/images/favicon.png' }]
['link', { rel: 'icon', href: baseUrl + '/images/favicon.svg' }]
],
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
@ -245,7 +245,11 @@ export default withMermaid({
copyright: 'OpenMCP All rights reserved'
},
search: {
provider: 'local'
},
// 左上角的 logo
logo: '/images/openmcp.png',
logo: '/images/favicon.svg',
}
})

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,8 @@
<template>
<DefaultTheme.Layout id="k-layout">
<template #home-hero-image>
<HeroImage />
</template>
</DefaultTheme.Layout>
<ClientOnly>
<ScrollBar v-if="mounted" />
@ -14,6 +17,8 @@ import mediumZoom from "medium-zoom";
import { animateIn, animateOut } from './hook/animate';
import ScrollBar from './components/scrollbar/index.vue';
import HeroImage from './components/home/HeroImage.vue';
import { gsap } from "gsap/dist/gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
@ -168,22 +173,4 @@ body::-webkit-scrollbar {
z-index: 999;
}
/* 淡入淡出动画 */
.fade-in {
opacity: 1;
}
.fade-out {
opacity: 0;
}
.slide-in {
transform: translateY(0);
opacity: 1;
}
.slide-out {
transform: translateY(100px);
opacity: 0;
}
</style>

View File

@ -1,25 +1,218 @@
<template>
<div style="height: 420px;">
<img class="VPImage image-src" src="/images/openmcp.png" alt="">
</div>
<div style="height: fit-content; width: fit-content; position: relative;" ref="container">
<svg class="VPImage image-src" viewBox="0 0 612 612" fill="none" xmlns="http://www.w3.org/2000/svg" ref="svgElement">
<defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" />
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2" />
</linearGradient>
<linearGradient id="gradient_2" gradientUnits="userSpaceOnUse" x1="110.5" y1="0" x2="110.5" y2="221">
<stop offset="0.468" stop-color="#BFBAF6" />
<stop offset="1" stop-color="#FFFFFF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-219" y="-219" width="221" height="221" id="filter_3">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_4" gradientUnits="userSpaceOnUse" x1="55.5" y1="0" x2="55.5" y2="111">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="1" stop-color="#A8A7F3" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-109" y="-109" width="111" height="111" id="filter_5">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_6" gradientUnits="userSpaceOnUse" x1="174" y1="0" x2="174" y2="348">
<stop offset="0.182" stop-color="#A594F6" />
<stop offset="1" stop-color="#F4E5FF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-346" y="-346" width="348" height="348" id="filter_7">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_8" gradientUnits="userSpaceOnUse" x1="57" y1="0" x2="57" y2="114">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="0.614" stop-color="#C7BAF8" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-112" y="-112" width="114" height="114" id="filter_9">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
</defs>
<g transform="translate(6 2)">
<g>
<path
d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z"
fill="#5A00FF" fill-rule="evenodd" />
<path
d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z"
fill="url(#gradient_1)" fill-rule="evenodd" />
</g>
<path
d="M0 110.5C0 49.4725 49.4725 0 110.5 0C171.527 0 221 49.4725 221 110.5C221 171.527 171.527 221 110.5 221C49.4725 221 0 171.527 0 110.5Z"
fill="url(#gradient_2)" fill-rule="evenodd" filter="url(#filter_3)"
transform="translate(293 324)" />
<path
d="M0 55.5C0 24.8482 24.8482 0 55.5 0C86.1518 0 111 24.8482 111 55.5C111 86.1518 86.1518 111 55.5 111C24.8482 111 0 86.1518 0 55.5Z"
fill="url(#gradient_4)" fill-rule="evenodd" filter="url(#filter_5)" transform="translate(48 269)" />
<path
d="M0 174C0 77.9024 77.9024 0 174 0C270.098 0 348 77.9024 348 174C348 270.098 270.098 348 174 348C77.9024 348 0 270.098 0 174Z"
fill="url(#gradient_6)" fill-rule="evenodd" filter="url(#filter_7)" transform="translate(188 56)" />
<path
d="M0 57C0 25.5198 25.5198 0 57 0C88.4802 0 114 25.5198 114 57C114 88.4802 88.4802 114 57 114C25.5198 114 0 88.4802 0 57Z"
fill="url(#gradient_8)" fill-rule="evenodd" filter="url(#filter_9)"
transform="translate(388 129)" />
</g>
</svg>
</div>
</template>
<style scoped>
<script setup>
import { onMounted, ref } from 'vue'
import { gsap } from 'gsap'
const container = ref(null)
const svgElement = ref(null)
onMounted(() => {
const paths = svgElement.value.querySelectorAll('path')
//
gsap.set(paths, {
strokeDasharray: (i, target) => {
const length = target.getTotalLength()
target.style.strokeDasharray = length
return length
},
strokeDashoffset: (i, target) => target.getTotalLength(),
stroke: 'var(--vp-c-brand-2)',
strokeWidth: 3,
fillOpacity: 0
})
// 线
const master = gsap.timeline()
// 线
const drawTimeline = gsap.timeline({
defaults: { duration: 1.5, ease: "power2.inOut" }
})
//
paths.forEach(path => {
drawTimeline.to(path, {
strokeDashoffset: 0,
}, "<+=0.3")
})
// 线
const reverseTimeline = gsap.timeline({
defaults: { duration: 1.5, ease: "power2.inOut" }
})
//
paths.forEach(path => {
reverseTimeline.to(path, {
fillOpacity: 1,
strokeDashoffset: (i, target) => target.getTotalLength()
}, "<")
})
// 线
const wiggleTimeline = gsap.timeline({
repeat: -1,
yoyo: true,
defaults: {
duration: 2,
ease: "sine.inOut"
}
})
//
const wiggleElements = [
{
el: svgElement.value.querySelector('[transform="translate(293 324)"]'),
x: "+=12", y: "+=5", rotation: "+=2"
},
{
el: svgElement.value.querySelector('[transform="translate(48 269)"]'),
x: "-=5", y: "-=10", rotation: "-=1"
},
{
el: svgElement.value.querySelector('[transform="translate(188 56)"]'),
x: "-=4", y: "+=5", rotation: "+=3"
},
{
el: svgElement.value.querySelector('[transform="translate(388 129)"]'),
x: "+=9", y: "+=4", rotation: "-=2"
}
]
//
wiggleElements.forEach(item => {
wiggleTimeline.to(item.el, {
x: item.x,
y: item.y,
rotation: item.rotation,
scale: item.scale,
transformOrigin: "center center"
}, "<")
})
//
master.add(drawTimeline)
.add(reverseTimeline, "+=0.5")
.add(wiggleTimeline) //
})
</script>
<style scoped>
.VPHero .VPImage {
filter: drop-shadow(-2px 4px 6px rgba(0, 0, 0, .2));
padding: 18px;
}
.image-src {
position: absolute;
top: 50%;
left: 50%;
max-width: 285px;
max-height: 285px;
height: 99%;
width: 320px;
height: 320px;
object-fit: contain;
transform: translate(-50%, -50%);
}
.circle-animation {
position: absolute;
top: 50%;
left: 50%;
width: 320px;
height: 320px;
transform: translate(-50%, -50%);
color: var(--vp-c-brand-1);
}
.circle-animation circle {
stroke-width: 3;
stroke-linecap: round;
}
</style>

View File

@ -13,7 +13,7 @@ interface ScrollbarController {
export const scrollbarController = reactive<ScrollbarController>({
element: undefined,
display: true,
height: 200,
height: 0,
width: 5,
top: 0,
opacity: 0,

View File

@ -44,9 +44,41 @@
}
.VPFeatures .item:hover .box {
background-color: var(--vp-c-brand-1);
}
.dark .VPButton.brand {
background-color: var(--vp-c-brand-3) !important;
}
.VPButton.brand {
background-color: var(--vp-c-brand-1) !important;
}
.dark .VPFeatures .item:hover .box {
background-color: var(--vp-c-brand-3);
}
.VPFeatures .item:hover .box .details {
color: var(--vp-c-white);
}
/* 淡入淡出动画 */
.fade-in {
opacity: 1;
}
.fade-out {
opacity: 0;
}
.slide-in {
transform: translateY(0);
opacity: 1;
}
.slide-out {
transform: translateY(100px);
opacity: 0;
}

View File

@ -72,6 +72,8 @@
--vp-c-danger-2: var(--vp-c-red-2);
--vp-c-danger-3: var(--vp-c-red-3);
--vp-c-danger-soft: var(--vp-c-red-soft);
--vp-bg-brand-2: rgba(194, 133, 214, 0.1);
}
/**

215
.vscode/tabs.my-browser.json vendored Normal file
View File

@ -0,0 +1,215 @@
{
"clientId": "81b3b1d6-b1d6-53b1d63c156-83b1d63c156a678-6a678e36",
"currentIndex": 0,
"tabs": [
{
"name": "交互测试",
"icon": "icon-robot",
"type": "blank",
"componentIndex": 3,
"storage": {
"activeNames": [
0
],
"messages": [
{
"role": "user",
"content": "使用 ffmpeg 把视频 (0, 65) 到 (1173, 769) 的位置截取出来,视频的格式是 mov我希望导出为 mp4",
"extraInfo": {
"created": 1749111492698,
"state": "success",
"serverName": "deepseek"
}
},
{
"role": "assistant",
"content": "你可以使用 `ffmpeg` 的 `crop` 滤镜来截取视频的指定区域,并将 `.mov` 转换为 `.mp4` 格式。以下是具体的命令:\n\n### 命令解析:\n1. **输入文件**`input.mov`(替换为你的文件名)\n2. **裁剪参数**\n - `crop=w:h:x:y`:从坐标 `(x,y)` 开始,截取宽度 `w`、高度 `h` 的区域。\n - 你的需求是从 `(0, 65)` 到 `(1173, 769)`,因此:\n - 宽度 `w = 1173 - 0 = 1173`\n - 高度 `h = 769 - 65 = 704`\n - 起始坐标 `(x,y) = (0, 65)`\n3. **输出格式**`mp4`(默认使用 H.264 编码)\n\n### 完整命令:\n```bash\nffmpeg -i input.mov -filter:v \"crop=1173:704:0:65\" -c:a copy output.mp4\n```\n\n### 参数说明:\n- `-i input.mov`:指定输入文件。\n- `-filter:v \"crop=1173:704:0:65\"`:视频裁剪滤镜。\n- `-c:a copy`:直接复制音频流(无需重新编码,节省时间)。\n- `output.mp4`:输出文件名。\n\n### 其他选项:\n- 如果需要控制视频质量,可以添加 `-crf` 参数(默认 23值越小质量越高\n ```bash\n ffmpeg -i input.mov -filter:v \"crop=1173:704:0:65\" -crf 18 -c:a copy output.mp4\n ```\n- 如果需要硬件加速(如 NVIDIA GPU可以添加 `-hwaccel cuda` 等参数。\n\n### 注意:\n1. 确保 `ffmpeg` 已安装并添加到系统路径。\n2. 如果视频有旋转/缩放等元数据,可能需要先处理(如用 `-vf \"transpose=1\"` 旋转)。\n\n运行命令后`output.mp4` 就是你需要的裁剪后视频。",
"extraInfo": {
"created": 1749111520497,
"state": "success",
"serverName": "deepseek",
"usage": {
"prompt_tokens": 42,
"completion_tokens": 487,
"total_tokens": 529,
"prompt_tokens_details": {
"cached_tokens": 0
},
"prompt_cache_hit_tokens": 0,
"prompt_cache_miss_tokens": 42
}
}
}
],
"settings": {
"modelIndex": 0,
"enableTools": [
{
"name": "k_navigate",
"description": "Navigate to a URL",
"inputSchema": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "URL to navigate to"
},
"launchOptions": {
"type": "object",
"description": "PuppeteerJS LaunchOptions. Default null. If changed and not null, browser restarts. Example: { headless: true, args: ['--no-sandbox'] }"
},
"allowDangerous": {
"type": "boolean",
"description": "Allow dangerous LaunchOptions that reduce security. When false, dangerous args like --no-sandbox will throw errors. Default false."
}
},
"required": [
"url"
]
},
"enabled": false
},
{
"name": "k_screenshot",
"description": "Take a screenshot of the current page or a specific element",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name for the screenshot"
},
"selector": {
"type": "string",
"description": "CSS selector for element to screenshot"
},
"width": {
"type": "number",
"description": "Width in pixels (default: 800)"
},
"height": {
"type": "number",
"description": "Height in pixels (default: 600)"
}
},
"required": [
"name"
]
},
"enabled": false
},
{
"name": "k_click",
"description": "Click an element on the page",
"inputSchema": {
"type": "object",
"properties": {
"selector": {
"type": "string",
"description": "CSS selector for element to click"
}
},
"required": [
"selector"
]
},
"enabled": false
},
{
"name": "k_fill",
"description": "Fill out an input field",
"inputSchema": {
"type": "object",
"properties": {
"selector": {
"type": "string",
"description": "CSS selector for input field"
},
"value": {
"type": "string",
"description": "Value to fill"
}
},
"required": [
"selector",
"value"
]
},
"enabled": false
},
{
"name": "k_select",
"description": "Select an element on the page with Select tag",
"inputSchema": {
"type": "object",
"properties": {
"selector": {
"type": "string",
"description": "CSS selector for element to select"
},
"value": {
"type": "string",
"description": "Value to select"
}
},
"required": [
"selector",
"value"
]
},
"enabled": false
},
{
"name": "k_hover",
"description": "Hover an element on the page",
"inputSchema": {
"type": "object",
"properties": {
"selector": {
"type": "string",
"description": "CSS selector for element to hover"
}
},
"required": [
"selector"
]
},
"enabled": false
},
{
"name": "k_evaluate",
"description": "Execute JavaScript in the browser console",
"inputSchema": {
"type": "object",
"properties": {
"script": {
"type": "string",
"description": "JavaScript code to execute"
}
},
"required": [
"script"
]
},
"enabled": false
},
{
"name": "k_get_full_page_text",
"description": "获取页面所有文本内容",
"inputSchema": {
"type": "object",
"properties": {}
},
"enabled": false
}
],
"enableWebSearch": false,
"temperature": 0.6,
"contextLength": 20,
"systemPrompt": "",
"parallelToolCalls": true
}
}
}
]
}

BIN
images/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

71
images/favicon.svg Normal file
View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="612" height="612" viewBox="0 0 612 612" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" />
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2" />
</linearGradient>
<linearGradient id="gradient_2" gradientUnits="userSpaceOnUse" x1="110.5" y1="0" x2="110.5" y2="221">
<stop offset="0.468" stop-color="#BFBAF6" />
<stop offset="1" stop-color="#FFFFFF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-219" y="-219" width="221" height="221" id="filter_3">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_4" gradientUnits="userSpaceOnUse" x1="55.5" y1="0" x2="55.5" y2="111">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="1" stop-color="#A8A7F3" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-109" y="-109" width="111" height="111" id="filter_5">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_6" gradientUnits="userSpaceOnUse" x1="174" y1="0" x2="174" y2="348">
<stop offset="0.182" stop-color="#A594F6" />
<stop offset="1" stop-color="#F4E5FF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-346" y="-346" width="348" height="348" id="filter_7">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_8" gradientUnits="userSpaceOnUse" x1="57" y1="0" x2="57" y2="114">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="0.614" stop-color="#C7BAF8" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-112" y="-112" width="114" height="114" id="filter_9">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
</defs>
<g transform="translate(6 2)">
<g>
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="#5A00FF" fill-rule="evenodd" />
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="url(#gradient_1)" fill-rule="evenodd" />
</g>
<path d="M0 110.5C0 49.4725 49.4725 0 110.5 0C171.527 0 221 49.4725 221 110.5C221 171.527 171.527 221 110.5 221C49.4725 221 0 171.527 0 110.5Z" fill="url(#gradient_2)" fill-rule="evenodd" filter="url(#filter_3)" transform="translate(293 324)" />
<path d="M0 55.5C0 24.8482 24.8482 0 55.5 0C86.1518 0 111 24.8482 111 55.5C111 86.1518 86.1518 111 55.5 111C24.8482 111 0 86.1518 0 55.5Z" fill="url(#gradient_4)" fill-rule="evenodd" filter="url(#filter_5)" transform="translate(48 269)" />
<path d="M0 174C0 77.9024 77.9024 0 174 0C270.098 0 348 77.9024 348 174C348 270.098 270.098 348 174 348C77.9024 348 0 270.098 0 174Z" fill="url(#gradient_6)" fill-rule="evenodd" filter="url(#filter_7)" transform="translate(188 56)" />
<path d="M0 57C0 25.5198 25.5198 0 57 0C88.4802 0 114 25.5198 114 57C114 88.4802 88.4802 114 57 114C25.5198 114 0 88.4802 0 57Z" fill="url(#gradient_8)" fill-rule="evenodd" filter="url(#filter_9)" transform="translate(388 129)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="612" height="612" viewBox="0 0 612 612" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" />
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2" />
</linearGradient>
<linearGradient id="gradient_2" gradientUnits="userSpaceOnUse" x1="110.5" y1="0" x2="110.5" y2="221">
<stop offset="0.468" stop-color="#BFBAF6" />
<stop offset="1" stop-color="#FFFFFF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-219" y="-219" width="221" height="221" id="filter_3">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_4" gradientUnits="userSpaceOnUse" x1="55.5" y1="0" x2="55.5" y2="111">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="1" stop-color="#A8A7F3" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-109" y="-109" width="111" height="111" id="filter_5">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_6" gradientUnits="userSpaceOnUse" x1="174" y1="0" x2="174" y2="348">
<stop offset="0.182" stop-color="#A594F6" />
<stop offset="1" stop-color="#F4E5FF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-346" y="-346" width="348" height="348" id="filter_7">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_8" gradientUnits="userSpaceOnUse" x1="57" y1="0" x2="57" y2="114">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="0.614" stop-color="#C7BAF8" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-112" y="-112" width="114" height="114" id="filter_9">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
</defs>
<g transform="translate(6 2)">
<g>
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="#5A00FF" fill-rule="evenodd" />
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="url(#gradient_1)" fill-rule="evenodd" />
</g>
<path d="M0 110.5C0 49.4725 49.4725 0 110.5 0C171.527 0 221 49.4725 221 110.5C221 171.527 171.527 221 110.5 221C49.4725 221 0 171.527 0 110.5Z" fill="url(#gradient_2)" fill-rule="evenodd" filter="url(#filter_3)" transform="translate(293 324)" />
<path d="M0 55.5C0 24.8482 24.8482 0 55.5 0C86.1518 0 111 24.8482 111 55.5C111 86.1518 86.1518 111 55.5 111C24.8482 111 0 86.1518 0 55.5Z" fill="url(#gradient_4)" fill-rule="evenodd" filter="url(#filter_5)" transform="translate(48 269)" />
<path d="M0 174C0 77.9024 77.9024 0 174 0C270.098 0 348 77.9024 348 174C348 270.098 270.098 348 174 348C77.9024 348 0 270.098 0 174Z" fill="url(#gradient_6)" fill-rule="evenodd" filter="url(#filter_7)" transform="translate(188 56)" />
<path d="M0 57C0 25.5198 25.5198 0 57 0C88.4802 0 114 25.5198 114 57C114 88.4802 88.4802 114 57 114C25.5198 114 0 88.4802 0 57Z" fill="url(#gradient_8)" fill-rule="evenodd" filter="url(#filter_9)" transform="translate(388 129)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -6,9 +6,6 @@ hero:
name: "OpenMCP"
text: "面向优雅开发者的 MCP 调试器和 SDK"
tagline: 缩短从大语言模型到智能体的最后一公里
image:
src: /images/openmcp.png
alt: VitePress
actions:
- theme: brand
@ -28,7 +25,7 @@ features:
title: 集成调试环境
details: 将检查器与 MCP 客户端功能相结合,实现无缝开发和测试
- icon:
src: /images/openmcp.png
src: /images/icons/openmcp-edge.svg
height: 48px
alt: 提供完整的项目级控制面板
title: 全面的项目管理

View File

@ -1,5 +1,14 @@
<div align="center" style="margin-bottom: 30px; border-radius: .5em; border: 1px solid var(--vp-c-brand-2); background-color: var(--vp-bg-brand-2); padding: 30px 10px;">
<img src="/images/icons/openmcp-sdk.svg" width="200px"/>
<h3>openmcp-sdk : 适用于 openmcp 的部署框架</h3>
<h4>闪电般将您的 agent 从实验室部署到生产环境</h4>
</div>
# 介绍 & 安装
## 什么是 openmcp-sdk.js
@ -27,35 +36,34 @@ pnpm add openmcp-sdk
```
:::
:::warning
目前 openmcp-sdk 只支持 esm 模式的导入
:::
## 使用
下面是一个最小例程:
文件名main.ts
```typescript
import { TaskLoop } from 'openmcp-sdk/task-loop';
import { TaskLoopAdapter } from 'openmcp-sdk/service';
async function main() {
// 创建适配器,负责通信和 mcp 连接
const adapter = new TaskLoopAdapter();
// 连接 mcp 服务器
await adapter.connectMcpServer({
// 添加 mcp 服务器
adapter.addMcp({
connectionType: 'STDIO',
command: 'node',
args: [
'~/projects/mcp/servers/src/puppeteer/dist/index.js'
]
commandString: 'node index.js',
cwd: '~/projects/openmcp-tutorial/my-browser/dist'
});
// 获取工具列表
const tools = await adapter.listTools();
// 创建事件循环驱动器, verbose 数值越高,输出的日志越详细
const taskLoop = new TaskLoop({ adapter, verbose: 1 });
// 创建事件循环驱动器
const taskLoop = new TaskLoop({ adapter });
// 获取所有工具
const tools = await taskLoop.getTools();
// 配置改次事件循环使用的大模型
taskLoop.setLlmConfig({
@ -70,8 +78,11 @@ async function main() {
messages: [],
settings: {
temperature: 0.7,
// 在本次对话使用所有工具
enableTools: tools,
// 系统提示词
systemPrompt: 'you are a clever bot',
// 对话上下文的轮数
contextLength: 20
}
};
@ -79,29 +90,64 @@ async function main() {
// 本次发出的问题
const message = 'hello world';
// 事件循环结束的句柄
taskLoop.registerOnDone(() => {
console.log('taskLoop done');
});
// 事件循环每一次 epoch 开始的句柄
taskLoop.registerOnError((error) => {
console.log('taskLoop error', error);
});
// 事件循环出现 error 时的句柄(出现 error 不一定会停止事件循环)
taskLoop.registerOnEpoch(() => {
console.log('taskLoop epoch');
});
// 开启事件循环
await taskLoop.start(storage, message);
// 打印上下文,最终的回答在 messages.at(-1) 中
console.log(storage.messages);
}
const content = storage.messages.at(-1).content;
console.log('最终回答:', content);
}
main();
```
star 我们的项目https://github.com/LSTM-Kirigaya/openmcp-client
以 esm 模块来运行它,先安装 typescript 的 esm 启动器:
```bash
npm install tsx --save-dev
```
运行上面的文件
```bash
npx tsx main.ts
```
下面是可能的输出:
```
[6/5/2025, 8:16:15 PM] 🚀 [my-browser] 0.1.0 connected
[6/5/2025, 8:16:15 PM] task loop enters a new epoch
[6/5/2025, 8:16:23 PM] task loop finish a epoch
[6/5/2025, 8:16:23 PM] 🤖 llm wants to call these tools k_navigate
[6/5/2025, 8:16:23 PM] 🔧 calling tool k_navigate
[6/5/2025, 8:16:34 PM] × fail to call tools McpError: MCP error -32603: net::ERR_CONNECTION_RESET at https://towardsdatascience.com/tag/editors-pick/
[6/5/2025, 8:16:34 PM] task loop enters a new epoch
[6/5/2025, 8:16:40 PM] task loop finish a epoch
[6/5/2025, 8:16:40 PM] 🤖 llm wants to call these tools k_navigate
[6/5/2025, 8:16:40 PM] 🔧 calling tool k_navigate
[6/5/2025, 8:16:44 PM] ✓ call tools okey dockey success
[6/5/2025, 8:16:44 PM] task loop enters a new epoch
[6/5/2025, 8:16:57 PM] task loop finish a epoch
[6/5/2025, 8:16:57 PM] 🤖 llm wants to call these tools k_evaluate
[6/5/2025, 8:16:57 PM] 🔧 calling tool k_evaluate
[6/5/2025, 8:16:57 PM] ✓ call tools okey dockey success
[6/5/2025, 8:16:57 PM] task loop enters a new epoch
[6/5/2025, 8:17:06 PM] task loop finish a epoch
[6/5/2025, 8:17:06 PM] 🤖 llm wants to call these tools k_navigate, k_navigate
[6/5/2025, 8:17:06 PM] 🔧 calling tool k_navigate
[6/5/2025, 8:17:09 PM] ✓ call tools okey dockey success
[6/5/2025, 8:17:09 PM] 🔧 calling tool k_navigate
[6/5/2025, 8:17:12 PM] ✓ call tools okey dockey success
[6/5/2025, 8:17:12 PM] task loop enters a new epoch
[6/5/2025, 8:17:19 PM] task loop finish a epoch
[6/5/2025, 8:17:19 PM] 🤖 llm wants to call these tools k_evaluate, k_evaluate
[6/5/2025, 8:17:19 PM] 🔧 calling tool k_evaluate
[6/5/2025, 8:17:19 PM] ✓ call tools okey dockey success
[6/5/2025, 8:17:19 PM] 🔧 calling tool k_evaluate
[6/5/2025, 8:17:19 PM] ✓ call tools okey dockey success
[6/5/2025, 8:17:19 PM] task loop enters a new epoch
[6/5/2025, 8:17:45 PM] task loop finish a epoch
"以下是整理好的热门文章信息,并已翻译为简体中文:\n\n---\n\n### K1 标题 \n**《数据漂移并非真正问题:你的监控策略才是》** \n\n**简介** \n在机器学习领域数据漂移常被视为模型性能下降的罪魁祸首但本文作者提出了一种颠覆性的观点数据漂移只是一个信号真正的核心问题在于监控策略的不足。文章通过实际案例如电商推荐系统和金融风控模型揭示了传统统计监控的局限性并提出了一个三层监控框架 \n1. **统计监控**:快速检测数据分布变化,但仅作为初步信号。 \n2. **上下文监控**:结合业务逻辑,判断漂移是否对关键指标产生影响。 \n3. **行为监控**:追踪模型预测的实际效果,避免“无声漂移”。 \n\n亮点在于作者强调了监控系统需要与业务目标紧密结合而非单纯依赖技术指标。 \n\n**原文链接** \n[点击阅读原文](https://towardsdatascience.com/data-drift-is-not-the-actual-problem-your-monitoring-strategy-is/) \n\n---\n\n### K2 标题 \n**《从 Jupyter 到程序员的快速入门指南》** \n\n**简介** \n本文为数据科学家和初学者提供了一条从 Jupyter Notebook 过渡到专业编程的清晰路径。作者通过实际代码示例和工具推荐(如 VS Code、Git 和 Docker帮助读者摆脱 Notebook 的局限性,提升代码的可维护性和可扩展性。 \n\n亮点包括 \n- 如何将 Notebook 代码模块化为可复用的 Python 脚本。 \n- 使用版本控制和容器化技术优化开发流程。 \n- 实战案例展示如何将实验性代码转化为生产级应用。 \n\n**原文链接** \n[点击阅读原文](https://towardsdatascience.com/the-journey-from-jupyter-to-programmer-a-quick-start-guide/) \n\n---\n\n如果需要进一步优化或补充其他内容请随时告诉我"
```