Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/youcom-web-search/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Optional You.com API key for higher quotas and enhanced features
# Without this, the tool uses keyless operation (100 free searches/day)
# Get your API key at: https://you.com/platform/api-keys
YDC_API_KEY=your-api-key-here
3 changes: 3 additions & 0 deletions examples/youcom-web-search/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.env
node_modules
dist
172 changes: 172 additions & 0 deletions examples/youcom-web-search/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# You.com Web Search MCP Tool

This example demonstrates how to integrate You.com's web search capabilities into a Skybridge MCP app, providing real-time web search functionality with rich interactive results.

## Features

- **Web search**: Search the web using You.com's powerful search engine
- **Keyless operation**: Works without API key (100 free searches per day)
- **Enhanced features**: Higher quotas and additional features with optional API key
- **Rich UI**: Interactive search results with titles, snippets, and source information
- **Search options**: Support for domain filtering, freshness filtering, and safe search
- **Real-time search**: Interactive search interface within the MCP app
- **Error handling**: Graceful handling of rate limits, API errors, and network issues

## Setup

### Quick Start (Keyless Mode)

No setup required! The tool works immediately with 100 free searches per day:

```bash
npm install
npm run dev
```

### Enhanced Mode (With API Key)

For higher quotas and enhanced features:

1. Get your API key at [you.com/platform/api-keys](https://you.com/platform/api-keys)
2. Create `.env` file:
```
YDC_API_KEY=your-api-key-here
```
3. Start the development server:
```bash
npm run dev
```

## Usage

### MCP Tool

The example registers a `youcom-search` tool with the following parameters:

- `query` (required): Search query string
- `count` (optional): Number of results (1-20, default: 10)
- `domains` (optional): Array of domains to restrict search to
- `freshness` (optional): Filter by content age ("hour", "day", "week", "month", "year")
- `safeSearch` (optional): Enable safe search filtering (default: true)

### Example Tool Calls

```typescript
// Basic search
await callTool("youcom-search", {
query: "TypeScript MCP frameworks"
});

// Advanced search with filters
await callTool("youcom-search", {
query: "React hooks patterns",
count: 15,
domains: ["reactjs.org", "github.com"],
freshness: "month",
safeSearch: true
});
```

### Interactive UI

The app provides a rich search interface with:

- Real-time search input
- Visual result cards with titles, snippets, and favicons
- Source domain display and external link indicators
- Loading states and error handling
- Search options display (keyless mode, domain filters, etc.)
- Responsive design that works across devices

## API Integration

The integration uses You.com's Search API:

- **Endpoint**: `https://api.you.com/v1/agents/search`
- **Authentication**: Optional Bearer token (`YDC_API_KEY`)
- **Rate limits**:
- Keyless: 100 searches/day per IP
- With API key: Higher quotas based on plan
- **Response format**: Structured JSON with web and news results

### Error Handling

The tool gracefully handles:

- **401 Unauthorized**: Invalid API key guidance
- **429 Rate Limited**: Clear messaging about quota limits with upgrade suggestions
- **5xx Server Errors**: Service availability notifications
- **Network errors**: Connection issue messaging
- **Malformed responses**: Data validation and fallbacks

## Implementation Details

### Architecture

```
src/
β”œβ”€β”€ youcom-client.ts # You.com API client with error handling
β”œβ”€β”€ server.ts # MCP server with tool registration
β”œβ”€β”€ helpers.ts # Type-safe tool calling helpers
β”œβ”€β”€ env.ts # Environment configuration
└── views/
└── youcom-search-results/
└── index.tsx # React search results UI
```

### Key Components

1. **YouComSearchClient**: Handles API communication, authentication, and error handling
2. **MCP Tool Registration**: Defines the tool schema and implementation
3. **React UI Component**: Interactive search interface with real-time updates
4. **Type Safety**: Full TypeScript support with proper type inference

### Integration Patterns

The example follows Skybridge's established patterns:

- Uses `McpServer.registerTool()` for tool definition
- Implements structured content for model consumption
- Provides rich UI views for human interaction
- Includes proper error handling and user feedback
- Supports both keyless and authenticated operation modes

## Development

```bash
# Install dependencies
npm install

# Development with hot reload
npm run dev

# Development with tunnel (for ChatGPT/Claude testing)
npm run dev:tunnel

# Build for production
npm run build

# Start production server
npm start
```

## Integration with AI Assistants

This MCP tool works seamlessly with:

- **Claude Code**: Install via plugin marketplace
- **ChatGPT**: Deploy as MCP app
- **VSCode Extensions**: Via MCP protocol
- **Any MCP Client**: Standard MCP tool interface

Ask your AI assistant to search for information:

> "Use the youcom-search tool to find recent TypeScript best practices"

> "Search for React 19 new features from the last month"

> "Find documentation about MCP servers on GitHub"

## License

MIT - see the main Skybridge repository for details.
42 changes: 42 additions & 0 deletions examples/youcom-web-search/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Workspace lockfile entry missing

When CI runs pnpm install --frozen-lockfile, the new workspace package has no importer in pnpm-lock.yaml, causing dependency installation to fail before the workspace can build.

Knowledge Base Used: Skills and Examples

Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/youcom-web-search/package.json
Line: 1

Comment:
**Workspace lockfile entry missing**

When CI runs `pnpm install --frozen-lockfile`, the new workspace package has no importer in `pnpm-lock.yaml`, causing dependency installation to fail before the workspace can build.

**Knowledge Base Used:** [Skills and Examples](https://app.greptile.com/skybridge/-/custom-context/knowledge-base/alpic-ai/skybridge/-/docs/skills-and-examples.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

"name": "skybridge-youcom-web-search-example",
"version": "0.0.1",
"private": true,
"description": "You.com Web Search MCP Tool Example",
"type": "module",
"scripts": {
"dev": "skybridge dev",
"dev:tunnel": "skybridge dev --tunnel",
"build": "skybridge build",
"start": "skybridge start"
},
"dependencies": {
"@alpic-ai/insights": "^1.142.1",
"@modelcontextprotocol/sdk": "^1.29.0",
"@t3-oss/env-core": "^0.13.11",
"clsx": "^2.1.1",
"dotenv": "^17.4.2",
"express": "^5.2.1",
"lucide-react": "^0.562.0",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"react-router-dom": "^7.18.0",
"skybridge": "^1.1.0",
"tailwind-merge": "^3.6.0",
"tailwindcss": "^4.3.1",
"zod": "^4.4.3"
},
"devDependencies": {
"@skybridge/devtools": "^1.2.3",
"@tailwindcss/vite": "^4.3.1",
"@types/express": "^5.0.6",
"@types/node": "^22.20.0",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.2",
"tsx": "^4.22.4",
"tw-animate-css": "^1.4.0",
"typescript": "^5.9.3",
"vite": "^8.1.5"
}
}
13 changes: 13 additions & 0 deletions examples/youcom-web-search/src/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import "dotenv/config";

import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";

export const env = createEnv({
server: {
NODE_ENV: z.enum(["development", "production"]).default("development"),
YDC_API_KEY: z.string().optional(),
},
runtimeEnv: process.env,
emptyStringAsUndefined: true,
});
4 changes: 4 additions & 0 deletions examples/youcom-web-search/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { generateHelpers } from "skybridge/web";
import type { AppType } from "./server.js";

export const { useCallTool, useToolInfo } = generateHelpers<AppType>();
96 changes: 96 additions & 0 deletions examples/youcom-web-search/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
@import "tailwindcss";
@import "tw-animate-css";

@custom-variant dark (&:is(.dark *));

@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
}

:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
}

.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
}

@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}

/* Utility classes for result cards */
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}

.line-clamp-3 {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
Loading