新的 gsap 片头入场动画
This commit is contained in:
parent
425cdb9e34
commit
a3f025185e
@ -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
@ -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>
|
@ -1,25 +1,218 @@
|
||||
<template>
|
||||
<div style="height: 420px;">
|
||||
<img class="VPImage image-src" src="/images/openmcp.png" alt="">
|
||||
<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>
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
@ -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
215
.vscode/tabs.my-browser.json
vendored
Normal 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
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
71
images/favicon.svg
Normal 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 |
BIN
images/icons/openmcp-edge.free
Normal file
BIN
images/icons/openmcp-edge.free
Normal file
Binary file not shown.
71
images/icons/openmcp-edge.svg
Normal file
71
images/icons/openmcp-edge.svg
Normal 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 |
5
index.md
5
index.md
@ -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: 全面的项目管理
|
||||
|
@ -3,11 +3,8 @@
|
||||
在使用 **SSE** 或 **Streamable HTTP** 进行连接时,为增强安全性可为接口设计鉴权机制,MCP 官方推荐采用 OAuth 协议。下面以获取 GitHub 用户信息为例,演示如何通过 openmcp-client 完成带 OAuth 认证的接口调试。
|
||||
|
||||
|
||||
## 部署服务器
|
||||
|
||||
|
||||
|
||||
### 1. 获取Github OAuth认证ID和secret
|
||||
## 1. 获取Github OAuth认证ID和secret
|
||||
|
||||
由于我们使用了Github用户信息相关API,需要先获取Github OAuth应用的Client ID和Client secret。
|
||||
|
||||
@ -19,7 +16,7 @@
|
||||
|
||||
注册成功后,请记录`Client ID`,然后点击`Generate a new client secret`生成一个`secret`,注意secret仅在生成的时候可见。
|
||||
|
||||
### 2. 设置环境变量
|
||||
## 2. 设置环境变量
|
||||
|
||||
在获取`Client ID`和`secret`之后,需要将其设置为环境变量:
|
||||
|
||||
@ -39,9 +36,9 @@ set MCP_GITHUB_GITHUB_CLIENT_SECRET={{secret}}
|
||||
|
||||
注意:cmd里面设置环境变量请不要加引号。
|
||||
|
||||
### 3. 克隆源码
|
||||
## 3. 克隆源码
|
||||
|
||||
首先,我们需要部署MCP服务器。可以参照[官方python例子](https://github.com/modelcontextprotocol/python-sdk/tree/main/examples/servers/simple-auth)进行。
|
||||
接下来,我们需要部署带有OAuth认证的MCP服务器。可以参照[官方python案例](https://github.com/modelcontextprotocol/python-sdk/tree/main/examples/servers/simple-auth)进行。
|
||||
|
||||
需要先克隆官方python-sdk源码:
|
||||
|
||||
@ -50,11 +47,11 @@ git clone https://github.com/modelcontextprotocol/python-sdk/ # 克隆源码
|
||||
cd examples/servers/simple-auth # 进入对应的目录
|
||||
```
|
||||
|
||||
### 4. 启动MCP Server
|
||||
## 4. 启动MCP Server
|
||||
|
||||
先根据需要创建虚拟环境安装依赖,然后直接运行`python main.py`即可,注意需要先设置环境变量,不然启动会报错`2 validation errors for ServerSettings`。
|
||||
先根据需要创建虚拟环境安装依赖,然后可以使用`uv`运行或者直接运行`python main.py`即可,注意需要先设置环境变量,不然启动会报错`2 validation errors for ServerSettings`。
|
||||
|
||||
### 5. 启动openmcp-client
|
||||
## 5. 启动openmcp-client
|
||||
|
||||
接下来,你就可以使用openmcp-client连接刚刚启动的server了,不管是使用网页端还是VSCode均可。
|
||||
|
||||
|
@ -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如果需要进一步优化或补充其他内容,请随时告诉我!"
|
||||
```
|
||||
|
Loading…
x
Reference in New Issue
Block a user