create-skybridge 0.0.0-dev.e0ed208 → 0.0.0-dev.e112094

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.js +169 -33
  3. package/dist/index.test.js +11 -1
  4. package/package.json +13 -13
  5. package/template/AGENTS.md +1 -0
  6. package/template/README.md +52 -24
  7. package/template/_gitignore +3 -1
  8. package/template/alpic.json +1 -2
  9. package/template/node_modules/.bin/alpic +21 -0
  10. package/template/node_modules/.bin/sb +21 -0
  11. package/template/node_modules/.bin/skybridge +21 -0
  12. package/template/node_modules/.bin/tsc +21 -0
  13. package/template/node_modules/.bin/tsserver +21 -0
  14. package/template/node_modules/.bin/tsx +21 -0
  15. package/template/node_modules/.bin/vite +21 -0
  16. package/template/package.json +24 -10
  17. package/template/src/components/ball.tsx +22 -0
  18. package/template/src/helpers.ts +4 -0
  19. package/template/src/index.css +152 -0
  20. package/template/{server/src → src}/server.ts +8 -13
  21. package/template/src/views/magic-8-ball.tsx +10 -0
  22. package/template/tsconfig.json +11 -0
  23. package/template/{web/vite.config.ts → vite.config.ts} +1 -3
  24. package/template/pnpm-workspace.yaml +0 -7
  25. package/template/server/nodemon.json +0 -5
  26. package/template/server/package.json +0 -32
  27. package/template/server/src/index.ts +0 -35
  28. package/template/server/src/middleware.ts +0 -54
  29. package/template/server/tsconfig.json +0 -17
  30. package/template/web/package.json +0 -24
  31. package/template/web/src/helpers.ts +0 -4
  32. package/template/web/src/index.css +0 -30
  33. package/template/web/src/widgets/magic-8-ball.tsx +0 -22
  34. package/template/web/tsconfig.app.json +0 -34
  35. package/template/web/tsconfig.json +0 -13
  36. package/template/web/tsconfig.node.json +0 -26
@@ -4,18 +4,32 @@
4
4
  "private": true,
5
5
  "description": "Alpic MCP Server Template",
6
6
  "type": "module",
7
- "packageManager": "pnpm@10.18.3",
8
7
  "scripts": {
9
- "dev": "pnpm --filter @apps-sdk-template/server dev",
10
- "build": "pnpm web:build && rm -rf server/dist && pnpm --filter=@apps-sdk-template/server --prod deploy server/dist && cp -r web/dist server/dist/assets && pnpm --filter=@apps-sdk-template/server build",
11
- "start": "pnpm server:start",
12
- "inspector": "pnpm --filter @apps-sdk-template/server inspector",
13
- "server:build": "pnpm --filter @apps-sdk-template/server build",
14
- "server:start": "pnpm --filter @apps-sdk-template/server start",
15
- "web:build": "pnpm --filter @apps-sdk-template/web build",
16
- "web:preview": "pnpm --filter @apps-sdk-template/web preview"
8
+ "dev": "skybridge dev",
9
+ "dev:tunnel": "skybridge dev --tunnel",
10
+ "build": "skybridge build",
11
+ "start": "skybridge start",
12
+ "deploy": "alpic deploy"
13
+ },
14
+ "dependencies": {
15
+ "@modelcontextprotocol/sdk": "^1.29.0",
16
+ "react": "^19.2.4",
17
+ "react-dom": "^19.2.4",
18
+ "skybridge": ">=0.0.0-dev.e112094",
19
+ "vite": "^8.0.3",
20
+ "zod": "^4.3.6"
17
21
  },
18
22
  "devDependencies": {
19
- "tsx": "^4.19.4"
23
+ "@skybridge/devtools": ">=0.35.14 <1.0.0",
24
+ "@types/node": "^24.12.0",
25
+ "@types/react": "^19.2.14",
26
+ "@types/react-dom": "^19.2.3",
27
+ "@vitejs/plugin-react": "^6.0.1",
28
+ "alpic": "^1.104.1",
29
+ "tsx": "^4.21.0",
30
+ "typescript": "^6.0.2"
31
+ },
32
+ "engines": {
33
+ "node": ">=24.14.1"
20
34
  }
21
35
  }
@@ -0,0 +1,22 @@
1
+ export function Ball({
2
+ question,
3
+ answer,
4
+ }: {
5
+ question?: string;
6
+ answer?: string;
7
+ }) {
8
+ return (
9
+ <div className="container">
10
+ <div className="ball">
11
+ {answer ? (
12
+ <>
13
+ <div className="question">{question}</div>
14
+ <div className="answer">{answer}</div>
15
+ </>
16
+ ) : (
17
+ <div className="question">Shaking...</div>
18
+ )}
19
+ </div>
20
+ </div>
21
+ );
22
+ }
@@ -0,0 +1,4 @@
1
+ import { generateHelpers } from "skybridge/web";
2
+ import type { AppType } from "./server.js";
3
+
4
+ export const { useToolInfo, useCallTool } = generateHelpers<AppType>();
@@ -0,0 +1,152 @@
1
+ @import url("https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@1,600&display=swap");
2
+
3
+ .container {
4
+ display: flex;
5
+ justify-content: center;
6
+ align-items: center;
7
+ min-height: 100%;
8
+ padding: 1rem;
9
+ box-sizing: border-box;
10
+ }
11
+
12
+ .ball {
13
+ background: radial-gradient(
14
+ circle at 30% 30%,
15
+ #454565 0%,
16
+ #1c1c30 40%,
17
+ #0a0a10 100%
18
+ );
19
+ border-radius: 50%;
20
+ width: 12rem;
21
+ height: 12rem;
22
+ display: flex;
23
+ flex-direction: column;
24
+ align-items: center;
25
+ justify-content: center;
26
+ font-family: monospace;
27
+ text-align: center;
28
+ position: relative;
29
+ box-shadow:
30
+ 0 10px 30px rgba(0, 0, 0, 0.5),
31
+ 0 5px 15px rgba(0, 0, 0, 0.3),
32
+ inset 0 -20px 40px rgba(0, 0, 0, 0.6);
33
+ animation:
34
+ float 3s ease-in-out infinite,
35
+ colorShift 15s ease-in-out infinite;
36
+ transition: transform 0.3s ease;
37
+ cursor: pointer;
38
+ border: 1px solid rgba(30, 30, 50, 0.6);
39
+ }
40
+
41
+ .ball:hover {
42
+ transform: scale(1.05) translateY(-8px);
43
+ animation: colorShift 15s ease-in-out infinite;
44
+ box-shadow:
45
+ 0 20px 50px rgba(0, 0, 0, 0.6),
46
+ 0 10px 25px rgba(0, 0, 0, 0.4),
47
+ inset 0 -20px 40px rgba(0, 0, 0, 0.6);
48
+ }
49
+
50
+ @keyframes float {
51
+ 0%,
52
+ 100% {
53
+ transform: translateY(0);
54
+ }
55
+ 50% {
56
+ transform: translateY(-8px);
57
+ }
58
+ }
59
+
60
+ @keyframes colorShift {
61
+ 0%,
62
+ 100% {
63
+ background: radial-gradient(
64
+ circle at 30% 30%,
65
+ #454565 0%,
66
+ #1c1c30 40%,
67
+ #0a0a10 100%
68
+ );
69
+ }
70
+ 25% {
71
+ background: radial-gradient(
72
+ circle at 30% 30%,
73
+ #3f4a65 0%,
74
+ #181e30 40%,
75
+ #090a10 100%
76
+ );
77
+ }
78
+ 50% {
79
+ background: radial-gradient(
80
+ circle at 30% 30%,
81
+ #3a5065 0%,
82
+ #152230 40%,
83
+ #080a10 100%
84
+ );
85
+ }
86
+ 75% {
87
+ background: radial-gradient(
88
+ circle at 30% 30%,
89
+ #3f4a65 0%,
90
+ #181e30 40%,
91
+ #090a10 100%
92
+ );
93
+ }
94
+ }
95
+
96
+ .ball::before {
97
+ content: "";
98
+ position: absolute;
99
+ top: 8%;
100
+ left: 20%;
101
+ width: 30%;
102
+ height: 20%;
103
+ background: radial-gradient(
104
+ ellipse,
105
+ rgba(255, 255, 255, 0.3) 0%,
106
+ transparent 70%
107
+ );
108
+ border-radius: 50%;
109
+ pointer-events: none;
110
+ }
111
+
112
+ .ball::after {
113
+ content: "";
114
+ position: absolute;
115
+ bottom: 8%;
116
+ right: 25%;
117
+ width: 25%;
118
+ height: 10%;
119
+ background: radial-gradient(
120
+ ellipse,
121
+ rgba(255, 255, 255, 0.1) 0%,
122
+ transparent 70%
123
+ );
124
+ border-radius: 50%;
125
+ pointer-events: none;
126
+ }
127
+
128
+ .question {
129
+ font-size: clamp(0.5rem, 2vw, 0.75rem);
130
+ color: lightgrey;
131
+ max-width: 90%;
132
+ word-wrap: break-word;
133
+ overflow-wrap: break-word;
134
+ text-align: center;
135
+ line-height: 1.3;
136
+ font-style: italic;
137
+ }
138
+
139
+ .answer {
140
+ font-family: "Playfair Display", serif;
141
+ font-style: italic;
142
+ font-size: 1.25rem;
143
+ font-weight: 600;
144
+ margin-top: 0.5rem;
145
+ color: #7dd3fc;
146
+ text-shadow: 0 0 10px rgba(125, 211, 252, 0.5);
147
+ max-width: 90%;
148
+ word-wrap: break-word;
149
+ overflow-wrap: break-word;
150
+ text-align: center;
151
+ line-height: 1.3;
152
+ }
@@ -3,10 +3,6 @@ import { z } from "zod";
3
3
 
4
4
  const Answers = [
5
5
  "As I see it, yes",
6
- "Ask again later",
7
- "Better not tell you now",
8
- "Cannot predict now",
9
- "Concentrate and ask again",
10
6
  "Don't count on it",
11
7
  "It is certain",
12
8
  "It is decidedly so",
@@ -15,7 +11,6 @@ const Answers = [
15
11
  "My sources say no",
16
12
  "Outlook good",
17
13
  "Outlook not so good",
18
- "Reply hazy, try again",
19
14
  "Signs point to yes",
20
15
  "Very doubtful",
21
16
  "Without a doubt",
@@ -30,27 +25,26 @@ const server = new McpServer(
30
25
  version: "0.0.1",
31
26
  },
32
27
  { capabilities: {} },
33
- ).registerWidget(
34
- "magic-8-ball",
35
- {
36
- description: "Magic 8 Ball",
37
- },
28
+ ).registerTool(
38
29
  {
30
+ name: "magic-8-ball",
39
31
  description: "For fortune-telling or seeking advice.",
40
32
  inputSchema: {
41
33
  question: z.string().describe("The user question."),
42
34
  },
35
+ view: {
36
+ component: "magic-8-ball",
37
+ description: "Magic 8 Ball",
38
+ },
43
39
  },
44
40
  async ({ question }) => {
45
41
  try {
46
- // deterministic answer
47
42
  const hash = question
48
43
  .split("")
49
44
  .reduce((acc, char) => acc + char.charCodeAt(0), 0);
50
45
  const answer = Answers[hash % Answers.length];
51
46
  return {
52
47
  structuredContent: { answer },
53
- content: [],
54
48
  isError: false,
55
49
  };
56
50
  } catch (error) {
@@ -62,5 +56,6 @@ const server = new McpServer(
62
56
  },
63
57
  );
64
58
 
65
- export default server;
59
+ server.run();
60
+
66
61
  export type AppType = typeof server;
@@ -0,0 +1,10 @@
1
+ import "@/index.css";
2
+
3
+ import { Ball } from "../components/ball.js";
4
+ import { useToolInfo } from "../helpers.js";
5
+
6
+ export default function Magic8Ball() {
7
+ const { input, output } = useToolInfo<"magic-8-ball">();
8
+
9
+ return <Ball question={input?.question} answer={output?.answer} />;
10
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "skybridge/tsconfig",
3
+
4
+ "compilerOptions": {
5
+ "paths": {
6
+ "@/*": ["./src/*"]
7
+ }
8
+ },
9
+
10
+ "include": ["src", ".skybridge/**/*.d.ts"]
11
+ }
@@ -1,12 +1,10 @@
1
1
  import path from "node:path";
2
2
  import react from "@vitejs/plugin-react";
3
- import { skybridge } from "skybridge/web";
3
+ import { skybridge } from "skybridge/vite";
4
4
  import { defineConfig } from "vite";
5
5
 
6
- // https://vite.dev/config/
7
6
  export default defineConfig({
8
7
  plugins: [skybridge(), react()],
9
-
10
8
  resolve: {
11
9
  alias: {
12
10
  "@": path.resolve(__dirname, "./src"),
@@ -1,7 +0,0 @@
1
- packages:
2
- - "web"
3
- - "server"
4
- sharedWorkspaceLockfile: false
5
-
6
- catalog:
7
- skybridge: ^0.13.1
@@ -1,5 +0,0 @@
1
- {
2
- "watch": ["src/**/*"],
3
- "ext": "ts,js,json",
4
- "exec": "tsx src/index.ts"
5
- }
@@ -1,32 +0,0 @@
1
- {
2
- "name": "@apps-sdk-template/server",
3
- "version": "0.0.1",
4
- "private": true,
5
- "main": "dist/index.js",
6
- "description": "Alpic MCP Server Template",
7
- "files": [
8
- "dist"
9
- ],
10
- "type": "module",
11
- "scripts": {
12
- "dev": "nodemon",
13
- "build": "tsc",
14
- "start": "node dist/index.js",
15
- "inspector": "mcp-inspector http://localhost:3000/mcp"
16
- },
17
- "dependencies": {
18
- "@modelcontextprotocol/sdk": "^1.24.3",
19
- "express": "^5.1.0",
20
- "skybridge": "catalog:",
21
- "vite": "^7.1.11",
22
- "zod": "^4.1.13"
23
- },
24
- "devDependencies": {
25
- "@modelcontextprotocol/inspector": "^0.17.5",
26
- "@types/express": "^5.0.3",
27
- "@types/node": "^22.15.30",
28
- "nodemon": "^3.1.10",
29
- "tsx": "^4.19.2",
30
- "typescript": "^5.7.2"
31
- }
32
- }
@@ -1,35 +0,0 @@
1
- import express, { type Express } from "express";
2
-
3
- import { widgetsDevServer } from "skybridge/server";
4
- import type { ViteDevServer } from "vite";
5
- import { mcp } from "./middleware.js";
6
- import server from "./server.js";
7
-
8
- const app = express() as Express & { vite: ViteDevServer };
9
-
10
- app.use(express.json());
11
-
12
- app.use(mcp(server));
13
-
14
- const env = process.env.NODE_ENV || "development";
15
-
16
- if (env !== "production") {
17
- app.use(await widgetsDevServer());
18
- }
19
-
20
- app.listen(3000, (error) => {
21
- if (error) {
22
- console.error("Failed to start server:", error);
23
- process.exit(1);
24
- }
25
-
26
- console.log(`Server listening on port 3000 - ${env}`);
27
- console.log(
28
- "Make your local server accessible with 'ngrok http 3000' and connect to ChatGPT with URL https://xxxxxx.ngrok-free.app/mcp",
29
- );
30
- });
31
-
32
- process.on("SIGINT", async () => {
33
- console.log("Server shutdown complete");
34
- process.exit(0);
35
- });
@@ -1,54 +0,0 @@
1
- import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
2
- import type { NextFunction, Request, Response } from "express";
3
-
4
- import type { McpServer } from "skybridge/server";
5
-
6
- export const mcp =
7
- (server: McpServer) =>
8
- async (req: Request, res: Response, next: NextFunction) => {
9
- // Only handle requests to the /mcp path
10
- if (req.path !== "/mcp") {
11
- return next();
12
- }
13
-
14
- if (req.method === "POST") {
15
- try {
16
- const transport = new StreamableHTTPServerTransport({
17
- sessionIdGenerator: undefined,
18
- });
19
-
20
- res.on("close", () => {
21
- transport.close();
22
- });
23
-
24
- await server.connect(transport);
25
-
26
- await transport.handleRequest(req, res, req.body);
27
- } catch (error) {
28
- console.error("Error handling MCP request:", error);
29
- if (!res.headersSent) {
30
- res.status(500).json({
31
- jsonrpc: "2.0",
32
- error: {
33
- code: -32603,
34
- message: "Internal server error",
35
- },
36
- id: null,
37
- });
38
- }
39
- }
40
- } else if (req.method === "GET" || req.method === "DELETE") {
41
- res.writeHead(405).end(
42
- JSON.stringify({
43
- jsonrpc: "2.0",
44
- error: {
45
- code: -32000,
46
- message: "Method not allowed.",
47
- },
48
- id: null,
49
- }),
50
- );
51
- } else {
52
- next();
53
- }
54
- };
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ESNext",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "esModuleInterop": true,
7
- "strict": true,
8
- "skipLibCheck": true,
9
- "forceConsistentCasingInFileNames": true,
10
- "outDir": "dist",
11
- "sourceMap": true,
12
- "jsx": "react",
13
- "inlineSources": true
14
- },
15
- "include": ["**/*.ts", "**/*.tsx"],
16
- "exclude": ["dist", "node_modules"]
17
- }
@@ -1,24 +0,0 @@
1
- {
2
- "name": "@apps-sdk-template/web",
3
- "private": true,
4
- "version": "0.0.0",
5
- "type": "module",
6
- "scripts": {
7
- "dev": "echo 'Not implemented",
8
- "build": "tsc -b && vite build",
9
- "preview": "vite preview"
10
- },
11
- "dependencies": {
12
- "skybridge": "catalog:",
13
- "react": "^19.1.1",
14
- "react-dom": "^19.1.1"
15
- },
16
- "devDependencies": {
17
- "@types/node": "^24.6.0",
18
- "@types/react": "^19.1.16",
19
- "@types/react-dom": "^19.1.9",
20
- "@vitejs/plugin-react": "^5.0.4",
21
- "typescript": "~5.9.3",
22
- "vite": "^7.1.11"
23
- }
24
- }
@@ -1,4 +0,0 @@
1
- import { generateHelpers } from "skybridge/web";
2
- import type { AppType } from "../../server/src/server";
3
-
4
- export const { useToolInfo } = generateHelpers<AppType>();
@@ -1,30 +0,0 @@
1
- .container {
2
- display: flex;
3
- justify-content: center;
4
- align-items: center;
5
- height: 100%;
6
- }
7
-
8
- .ball {
9
- background-color: black;
10
- border-radius: 50%;
11
- width: 12rem;
12
- height: 12rem;
13
- display: flex;
14
- flex-direction: column;
15
- align-items: center;
16
- justify-content: center;
17
- font-family: monospace;
18
- }
19
-
20
- .question {
21
- font-size: 0.75rem;
22
- color: lightgrey;
23
- }
24
-
25
- .answer {
26
- font-size: 1.125rem;
27
- font-weight: bold;
28
- margin-top: 0.5rem;
29
- color: aqua;
30
- }
@@ -1,22 +0,0 @@
1
- import "@/index.css";
2
-
3
- import { mountWidget } from "skybridge/web";
4
- import { useToolInfo } from "../helpers";
5
-
6
- function Magic8Ball() {
7
- const { input, output } = useToolInfo<"magic-8-ball">();
8
- if (!output) return <div>Shaking...</div>;
9
-
10
- return (
11
- <div className="container">
12
- <div className="ball">
13
- <div className="question">{input.question}</div>
14
- <div className="answer">{output.answer}</div>
15
- </div>
16
- </div>
17
- );
18
- }
19
-
20
- export default Magic8Ball;
21
-
22
- mountWidget(<Magic8Ball />);
@@ -1,34 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
- "target": "ES2022",
5
- "useDefineForClassFields": true,
6
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
- "module": "ESNext",
8
- "types": ["vite/client"],
9
- "skipLibCheck": true,
10
-
11
- /* Bundler mode */
12
- "moduleResolution": "bundler",
13
- "allowImportingTsExtensions": true,
14
- "verbatimModuleSyntax": true,
15
- "moduleDetection": "force",
16
- "noEmit": true,
17
- "jsx": "react-jsx",
18
-
19
- /* Linting */
20
- "strict": true,
21
- "noUnusedLocals": true,
22
- "noUnusedParameters": true,
23
- "erasableSyntaxOnly": true,
24
- "noFallthroughCasesInSwitch": true,
25
- "noUncheckedSideEffectImports": true,
26
-
27
- /* Shadcn Config */
28
- "baseUrl": ".",
29
- "paths": {
30
- "@/*": ["./src/*"]
31
- }
32
- },
33
- "include": ["src"]
34
- }
@@ -1,13 +0,0 @@
1
- {
2
- "files": [],
3
- "references": [
4
- { "path": "./tsconfig.app.json" },
5
- { "path": "./tsconfig.node.json" }
6
- ],
7
- "compilerOptions": {
8
- "baseUrl": ".",
9
- "paths": {
10
- "@/*": ["./src/*"]
11
- }
12
- }
13
- }
@@ -1,26 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
- "target": "ES2023",
5
- "lib": ["ES2023"],
6
- "module": "ESNext",
7
- "types": ["node"],
8
- "skipLibCheck": true,
9
-
10
- /* Bundler mode */
11
- "moduleResolution": "bundler",
12
- "allowImportingTsExtensions": true,
13
- "verbatimModuleSyntax": true,
14
- "moduleDetection": "force",
15
- "noEmit": true,
16
-
17
- /* Linting */
18
- "strict": true,
19
- "noUnusedLocals": true,
20
- "noUnusedParameters": true,
21
- "erasableSyntaxOnly": true,
22
- "noFallthroughCasesInSwitch": true,
23
- "noUncheckedSideEffectImports": true
24
- },
25
- "include": ["vite.config.ts"]
26
- }